Упомянутые метаданные - это информация, хранящаяся в формате XML, о типах возврата и аргументов методов Objective-C. Это необходимо для того, чтобы мост PyObjC знал, в какой тип превратить объект Python при передаче его обратно в код Objective-C. Вы можете проверить метаданные, если хотите; он находится в файлах .bridgesupport внутри платформы PyObjC. Например, метаданные AppKit находятся по адресу /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/AppKit/PyObjC.bridgesupport. Их можно сгенерировать для любого кода Objective-C, который вы используете gen_bridge_metadata
инструмент командной строки от Apple. Для этой утилиты есть справочная страница , и man 5 BridgeSupport
также информативен. 1
PyObjC предоставляет функции objc.registerMetaDataForSelector
и objc.parseBridgeSupport
, которые позволяют добавлять метаданные для ваших методов, используя либо Python dicts (первая функция), либо формат XML, описанный на справочной странице BridgeSupport (последняя) , Примеры использования 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>
Спецификаторы типа arg - это те же Кодировки типов , которые вы получаете от использования @encode
в Obj-C. Метаданные для вашего метода должны быть очень похожими.
Итак, поскольку у вас есть прототипы ваших методов в 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 и возвращаемые параметры | Метод индексированного доступа | Проблема с openPanelDidEnd . Возможно, вы тоже захотите взглянуть на них.
Прошло много времени с тех пор, как я с этим справился, так что, возможно, я что-то упустил. Не стесняйтесь спрашивать дополнительную информацию, если вы все еще не можете заставить это работать. Но не сдавайтесь слишком легко - мост - забавный зверь, и иногда вам просто нужно показать, кто в доме хозяин!
1 Еще один документ Apple, который вы должны прочитать: Создание метаданных платформы .
2 Я обнаружил их через ветку списка рассылки pyobjc-dev