2017-09-14 28 views
2

我有我的目標C文件中的函數(可以說類MyBlockExecutor):如何調用一個接受來自Swift參數塊的字典的Objective-C函數?

+ (void) runBlockFromDictionary: (NSDictionary*) blocksDict andKey: (NSString*) key 
{ 
    if ([blocksDict objectForKey: key] != nil) 
    { 
     ((MyBlock)[blocksDict objectForKey: key])(); 
    } 
} 

現在,我想打電話從斯威夫特此功能。這是我的快速通話:

MyBlockExecutor.runBlock(from: [ 
     "key1":{()->Void in 
        print("block for key1 called") 
       } 
     ], andKey: "key1") 

這使我的應用程序崩潰。我在這一行獲得EXC_BAD_ACCESS錯誤:

((MyBlock)[blocksDict objectForKey: key])(); 

雖然,調用同一個功能從Objective-C的工作完全正常。 此外,我已將MyBlock定義爲:

typedef void (^MyBlock)(); //defined in MyBlockExecutor.h file 

如何解決此問題?我打開目標c函數的變化,我只是需要傳遞一個從swift到我的客觀c函數的閉包集合並運行該塊。

回答

2

你可以使用類似的方法在Swift blocks not working:註釋與@convention(block) 塊使用Objective-C的塊調用約定,以及(明確)投 它AnyObject將其放入字典之前:

let myBlock: @convention(block)() -> Void = { 
    print("block for key1 called") 
} 

let dict = ["key1": myBlock as AnyObject] 

MyBlockExecutor.runBlock(from: dict, andKey: "key1") 

這在我的測試中按預期工作。

它也類似於Quinn的「愛斯基摩!」在 the Apple developer forum建議作爲一個方法 傳遞一個封閉件(在夫特定義)作爲通過指針一個Objective-C兼容 對象,只有我取代了unsafeBitCast 由簡單的as AnyObject

你也可以寫的一切在線:

MyBlockExecutor.runBlock(from: ["key1": { 
     print("block for key1 called") 
    } as @convention(block)() -> Void as AnyObject 
    ], andKey: "key1") 

或定義一個輔助函數:

func objcBlock(from block: @convention(block)() -> Void) -> AnyObject { 
    return block as AnyObject 
} 

MyBlockExecutor.runBlock(from: ["key1": objcBlock { 
     print("block for key1 called") 
    }], andKey: "key1") 
+0

這工作!另外,你能告訴我怎麼做這個內聯,即,我不想創建myBlock和字典變量。 – user2473992

+0

@ user2473992:查看更新。 –

0

試圖打破代碼段,並從其中的錯誤來了檢查..雖然其近同你做了什麼,我們剛剛打破多行代碼進行調試容易

//1. create the block instance separately 
let myBlockForKey1:MyBlock = {() in 
    print("block for key1 called") 
} 
//2. create dic of blocks as 
let dicOfBlocks:[String:MyBlock] = ["key1":myBlockForKey1] 
//3. call your function 
MyBlockExecutor.runBlock(from: dicOfBlocks, andKey: "key1") 
相關問題