Опитвам се да изградя обект-C блок в Swift 2, за да го добавим към NSArray
така :
typealias CompletionBlock = () -> Void
let aBlock:CompletionBlock = {
print("Hello world!")
}
let nsArray = NSMutableArray()
nsArray.addObject(aBlock) // Error
Знам, че ще работи добре с масив Swift, но имам нужда от него NSArray
тук за съвместимост със съществуващия код на Цел-С. И ако използвам бърз масив, съставителят ще откаже да го хвърли на един NSArray
защото няма да бъде [AnyObject]
(това ще бъде [Any]
).
Проблемът тук е, че бързото затваряне не е обект, противоречащ на блоковете на Цел-С, които са обекти зад сцената (те са случаи на NSBlock
който е подклас на NSObject
)
Така че въпросът ми е: Как да създадете обект-C блок в бърз? Опитах да използвам @convention (block)
в типията, но тя не работи.
Отговори:
6 за отговор № 1РЕДАКТИРАНЕ : От Swift 3, това е напълно ненужно (и дори не работи). Добавянето на затваряне към обектите на Цел-С работи извън кутията в Swift 3. Отговорът по-долу е валиден само за Swift 2.
Знам, че това е дубликат, но все пак ще публикувам отзивчив отговор бързо затваряне, както-anyobject и чугунени калодки затваряне в случай че първо се качи на някого.
Решението е да се използва unsafeBitCast
функция за преобразуване на затварянето на Swift в съвместим с Objective-C обект, преди да го добавите към NSArray
и преди да го използвате в Swift.
// The `@convention(block)` is important here in order to get
// Objective-C like memory management
typealias CompletionBlock = @convention(block) () -> Void
let aBlock:CompletionBlock = {
print("Hello world!")
}
let nsArray = NSMutableArray()
let blockObject = unsafeBitCast(aBlock, AnyObject.self)
nsArray.addObject(blockObject)
let closureObject = nsArray[0]
let closure = unsafeBitCast(closureObject, CompletionBlock.self)
closure()