官方文档说可以在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)
问题是somehow_pass_completion
的外观以及如何为myBlock
提供元数据。
答案 0 :(得分: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 page,而man 5 BridgeSupport
也提供了信息。 1
PyObjC提供函数objc.registerMetaDataForSelector
和objc.parseBridgeSupport
,这两个函数都允许您使用Python dicts(前一个函数)或BridgeSupport手册页中描述的XML格式为您的方法添加元数据(后者)。 pyobjc源代码中提供了使用registerMetaData...
的示例: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>
arg类型说明符与您在Obj-C中使用@encode
时获得的Type Encodings相同。您的方法的元数据应该非常相似。
因此,既然您已经在Objective-C中使用了原型方法,那么您应该能够通过gen_bridge_metadata
运行它们来创建可以包含在项目中的.bridgesupport文件,然后使用objc.parseBridgeSupport
读取该文件。使用objc.registerMetaDataForSelector
过去也对我有用;看看上面链接的例子。
在PyObjC“系统”中获得元数据后,您可以使用任何旧的可调用对象作为获取块的方法的参数:
def pythonMethod():
def myCompletionHandler(obj, error):
pass
foo = SomeClass.new()
foo.doSomethingWithCompletion_(myCompletionHandler)
这是我在这里发表的关于PyObjC的一些其他帖子的混合物:PyObjC and Returning Out Parameters | Indexed Accessor Method | Problem with openPanelDidEnd。您可能也想看看这些。
我已经有一段时间了,所以我可能已经遗漏了一些东西。如果您仍然无法使用此功能,请随时询问更多信息。不要轻易放弃 - 桥梁是一个有趣的野兽,有时你只需要告诉它谁是老板!
1 您应阅读的另一个Apple文档是:Generating Framework Metadata。
2 我通过pyobjc-dev mailing list thread发现了这些