Литые крышки / блоки
В Objective-C я часто раздаю блоки. Я использую их очень часто для реализации шаблонов, которые помогают избежать хранения вещей в переменных экземпляра, тем самым избегая проблем с потоками / синхронизацией.
Например, я назначаю ихCAAnimation
с помощью-[CAAnimation setValue:forKey:]
так что я могу выполнить блок, когда анимация закончена. (Objective-C может обрабатывать блоки как объекты; вы также можете сделать[someBlock copy]
а также[someBlock release]
.)
Однако попытка использовать эти шаблоны в Swift вместе с Objective-C кажется очень сложной. (Редактировать: и мы можем видеть, что язык все еще в движении: адаптировали код, чтобы он работал на Xcode6-beta2, предыдущая версия работала на Xcode6-beta1.)
Например, я не могу конвертироватьAnyObject
Вернуться к блоку / закрытию. Следующее приводит к ошибке от компилятора:
override func animationDidStop(anim: CAAnimation!, finished flag: Bool)
{
let completion : AnyObject! = anim.valueForKey("completionClosure")
(completion as (@objc_block ()->Void))()
// Cannot convert the expression's type 'Void' to type '@objc_block () -> Void'
}
Я нашел обходной путь, но это довольно уродливо, ИМХО: в моем соединительном заголовке у меня есть:
static inline id blockToObject(void(^block)())
{
return block;
}
static inline void callBlockAsObject(id block)
{
((void(^)())block)();
}
И теперь я могу сделать это в Swift:
func someFunc(completion: (@objc_block ()->Void))
{
let animation = CAKeyframeAnimation(keyPath: "position")
animation.delegate = self
animation.setValue(blockToObject(completion), forKey: "completionClosure")
…
}
override func animationDidStop(anim: CAAnimation!, finished flag: Bool)
{
let completion : AnyObject! = anim.valueForKey("completionClosure")
callBlockAsObject(completion)
}
Это работает, но мне нужна новая функция для каждого типа блока, который я хотел бы использовать, и я хакиваю компилятор, который тоже не может быть хорошим.
Так есть ли способ решить это чисто Swift?