2017-09-14 27 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") 
相关问题