2015-09-25 6 views
3

здесь блок ObjectiveCКак сохранить этот объект objectC внутри быстрой переменной?

@property (copy) void (^anObjcBlock)(); 

anObjcBlock = ^{ 
    NSLog(@"Yea man this thing works!!"); 
}; 
NSMutableArray *theArrayThatHasTheBlockInItAtIndexZero = [NSmutableArray array]; 
[theArrayThatHasTheBlockInItAtIndexZero addObject:anObjBlock]; 

Вот что я сделал в скор:

var theBlock: (()->Void) ? 

theBlock = theArrayThatHasTheBlockInItAtIndexZero[0] as?()->Void 
//Now call the block 
theBlock!() 

Но с этим я получаю ошибку во время выполнения. В принципе, заявление theBlock = theArrayThatHasTheBlockInItAtIndexZero[0] as?()->Void составило бы theBlock ноль, потому что as? потерпел неудачу. И когда я сменил заявление на theBlock = theArrayThatHasTheBlockInItAtIndexZero[0] as!()->Void, я получил ошибку времени выполнения. enter image description here

Я не уверен, что еще делать. Это пустой проект, в нем действительно нет кода.

+0

Вы можете попытаться окружить определение блока с помощью кронштейна? var theBlock: (() -> Void)? –

+0

Да, извините. Я уже сделал это в скобках. Я отредактировал вопрос –

+0

Тай, чтобы установить тип блока в 'var block: (@convention (block)() -> Void)?'. (Swift 2.0 - для Swift 1.x используйте '@ objc_block' вместо' @convention (block') –

ответ

4

Похоже, что проблема в этом случае исходит от NSMutableArray.

[NSMutableArray objectAtIndex:] возвращает ID в Objective-C, который транслируется в AnyObject от Swift.

Вы получите сообщение об ошибке, если вы пытаетесь бросить AnyObject к () -> Пустота.

Обходной является следующее:

//Create your own typealias (we need this for unsafeBitcast) 
typealias MyType = @convention(block)() -> Void 

//Get the Obj-C block as AnyObject 
let objcBlock : AnyObject = array.firstObject! // or [0] 

// Bitcast the AnyObject Objective-C block to a "Swifty" Objective-C block (@convention(block)) 
//and then assign the result to a variable of() -> Void type 

let block :() -> Void = unsafeBitCast(objcBlock, MyType.self) 

//Call the block 

block() 

Этот код работает для меня.


FUNNY FACT

При редактировании кода Objective-C, чтобы выглядеть следующим образом ...

//Typedef your block type 
typedef void (^MyType)(); 

//Declare your property as NSArray of type MyType 
@property (strong) NSArray<MyType>* array; 

Swift теперь будет сообщать тип массива, как [MyType]!.

По какой-то причине дженерики на NSMutableArray, похоже, не подхватили Swift.

Несмотря на это, вы получите сообщение об ошибке выполнения, если вы выполняете:

let block : MyType? = array[0] 
+1

Спасибо! wow .. Я смотрю, что именно вы сделали. –

+1

Вам нужен тип, чтобы использовать unsafeBitcast.Поскольку вы не можете использовать '() -> Void' как тип, трюк состоит в том, чтобы создать для него typealias, поэтому вы можете ссылаться на него, как в моем коде, используя' .self'. Затем вам нужно небезопасноBitcast ваш блок типа typealias. Swift затем «помнит», что такое тип блока, поэтому блок objc справа преобразуется в закрытие Swift слева. Надеюсь, это поможет. –

Смежные вопросы