如何调用一个Objective-C函数,它接受Swift的块词典作为参数? [英] How to call an objective-c function which accepts Dictionary of blocks as argument from Swift?

查看:175
本文介绍了如何调用一个Objective-C函数,它接受Swift的块词典作为参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的目标c文件中有一个函数(比如说MyBlockExecutor类):

I have a function in my objective c file (lets say class MyBlockExecutor):

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

现在,我想从Swift调用此函数.这是我的快捷电话:

Now, I want to call this function from Swift. Here is my swift call:

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

这会使我的应用程序崩溃.我在此行上收到EXC_BAD_ACCESS错误:

This crashes my app. I am getting EXC_BAD_ACCESS error on this line:

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

尽管,从Objective-C调用相同的函数也可以很好地工作. 另外,我将MyBlock定义为:

Although, calling the same function from Objective-C works perfectly fine. Also, I've defined MyBlock as :

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

我该如何解决?

我对目标c函数的变化持开放态度,只是我需要以某种方式将闭包的集合从swift传递给我的目标c函数并运行该块.

I am open to changes in the objective c function, I just somehow need to pass a collection of closures from swift to my objective c function and run the block.

推荐答案

您可以使用与

You can use a similar approach as in Swift blocks not working: Annotate the block with @convention(block) to use the Objective-C block calling convention, and (explicitly) cast it to AnyObject before putting it into the dictionary:

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

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

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

这如我的测试中预期的那样工作.

This worked as expected in my test.

它也类似于奎因(Quinn)的《爱斯基摩人》!建议中 Apple开发者论坛作为一种方法 将闭包(在Swift中定义)传递为与Objective-C兼容 通过指针对象,只有我替换了unsafeBitCast 通过更简单的as AnyObject.

It is also similar to what Quinn "The Eskimo!" suggested in the Apple developer forum as a method to pass a closure (defined in Swift) as an Objective-C compatible object through pointers, only that I replaced the unsafeBitCast by the simpler as AnyObject.

您还可以内联编写所有内容:

You can also write everything inline:

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")

这篇关于如何调用一个Objective-C函数,它接受Swift的块词典作为参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆