PyObjC和自定义块

Ken*_*tzo 5 macos cocoa pyobjc

官方文档说可以在python代码中使用自定义块,但是您需要创建元数据.我还没有找到它的一个例子.

我的问题是如何创建,使用和分发自定义块的元数据.

@interface SomeClass

- (void)doSomethingWithCompletion: (void (^)(SomeObject *obj, NSError *error))myBlock;

@end


def pythonMethod():
    def completion(obj, error):
        # staff
    foo = SomeClass.new()
    foo.doSomethingWithCompletion_(somehow_pass_completion)
Run Code Online (Sandbox Code Playgroud)

问题是somehow_pass_completion应该如何以及如何提供元数据myBlock.

Jos*_*ell 6

提到的元数据是以XML格式存储的有关Objective-C方法的返回和参数类型的信息.需要它以便PyObjC桥知道在将Python对象传回Objective-C代码时将其转换为什么类型.如果您愿意,可以查看元数据; 它位于PyObjC框架内的.bridgesupport文件中.例如,AppKit元数据位于/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/AppKit/PyObjC.bridgesupport可以为您使用的任何Objective-C代码生成它Apple的gen_bridge_metadata命令行工具.这是该实用程序的手册页,man 5 BridgeSupport也提供了丰富的信息.1

PyObjC提供的功能objc.registerMetaDataForSelectorobjc.parseBridgeSupport,两者都允许你添加元数据的方法,即使用Python的类型的字典(原函数),或在BridgeSupport手册页(后)中所描述的XML格式.registerMetaData...pyobjc源中提供了使用示例:pyobjc/pyobjc-core/PyObjCTest/test_metadata* (和附近的test_metadata*.py文件)2.

举个例子,这是元数据-[NSSavePanel beginWithCompletionHandler:],它以块作为参数:

<method selector='beginWithCompletionHandler:'>
    <arg index='0' block='true' >
        <retval type='v' />
        <arg type='i' type64='q' />
    </arg>
</method>
Run Code Online (Sandbox Code Playgroud)

arg类型说明符与您在Obj-C中使用的类型编码相同@encode.您的方法的元数据应该非常相似.

因此,既然您已经在Objective-C中使用了原型方法,那么您应该能够运行它们gen_bridge_metadata来创建一个.bridgesupport文件,您可以将其包含在项目中,然后objc.parseBridgeSupport用来读取该文件.使用objc.registerMetaDataForSelector对我来说也有用处过去; 查看上面链接的示例.

一旦在PyObjC"系统"中获得元数据,就可以使用任何旧的可调用对象作为获取块的方法的参数:

def pythonMethod():
    def myCompletionHandler(obj, error):
        pass
foo = SomeClass.new()
foo.doSomethingWithCompletion_(myCompletionHandler)
Run Code Online (Sandbox Code Playgroud)

这是我在这里关于PyObjC的一些其他帖子的混合:PyObjC和返回参数 | 索引存取方法 | openPanelDidEnd问题.您可能也想看看这些.

我已经有一段时间了,所以我可能已经遗漏了一些东西.如果您仍然无法使用此功能,请随时询问更多信息.不要轻易放弃 - 桥是一个有趣的野兽,有时你只需要告诉它谁是老板!


1您应该阅读的另一个Apple文档是:生成框架元数据.
2我通过pyobjc-dev 邮件列表线程发现了这些