В 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 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?