我正在尝试按照the KVC guide在Python中为我的模型类实现索引访问器方法。我想使用可选的ranged方法,出于性能原因一次加载多个对象。该方法采用指向C数组缓冲区的指针,我的方法需要将对象复制到其中。我尝试了类似下面的东西,但是没有用。我该如何做到这一点?
@objc.accessor # i've also tried @objc.signature('v@:o^@')
def getFoos_range_(self, range):
return self._some_array[range.location:range.location + range.length]
编辑:在Apple移动了所有文档后,我终于找到了type encodings reference。读完之后,我试了一下:
@objc.signature('v@:N^@@')
def getFoos_range_(self, buf, range):
但这似乎也没有用。第一个参数应该是一个指向C数组的指针,但是长度在运行时才知道,所以我不确切知道如何构造正确的类型编码。我试过'v@:N^[1000@]@'
只是为了看,但这也不起作用。
我的模型对象绑定到驱动表视图的NSArrayController的contentArray。它似乎根本没有调用这个方法,可能是因为它期望的签名不同于桥提供的签名。有什么建议吗?
答案 0 :(得分:2)
你很亲密。此方法的正确装饰器是:
@objc.signature('v@:o^@{_NSRange=QQ}')
NSRange
不是对象,而是结构,不能简单地指定为@
;你需要包括成员 1 。
不幸的是,这不是它的结束。在对PyObjC源进行了大量的实验和研究后,我终于发现,为了使这种方法起作用,你还需要为该签名冗余的方法指定元数据。 (但是,我仍然不知道为什么。)
这是使用函数objc.registerMetaDataForSelector
:
objc.registerMetaDataForSelector(b"SUPERCLASSNAME",
b"getKey:range:",
dict(retval=dict(type=objc._C_VOID),
arguments={
2+0: dict(type_modifier=objc._C_OUT,
c_array_length_in_arg=2+1),
2+1: dict(type=b'{_NSRange=II}',
type64=b'{_NSRange=QQ}')
}
)
)
可以在PyObjC源文件test_metadata_py.py
(和附近的test_metadata*.py
文件)中找到使用此函数的示例和一些细节。
NB 必须在您感兴趣实现get<Key>:range:
的任何类的超类上指定元数据,并且此函数还需要在类定义结束之前的某个时间被调用(但是在class
语句之前或之内本身都可以工作)。我还没有把这些问题困惑。
我在Foundation PyObjC.bridgesupport文件 2 中将此元数据基于NSArray getObjects:range:
的元数据,并在参考Apple的BridgeSupport manpage时获得了帮助。
有了这个,这也值得注意,定义方法的最简单方法是(至少,IMO):
@objc.signature('v@:o^@{_NSRange=QQ}')
def get<#Key#>_range_(self, buf, inRange):
#NSLog(u"get<#Key#>")
return self.<#Key#>.getObjects_range_(buf, inRange)
即,使用数组的内置getObjects:range:
。
1:在32位Python上,QQ
,意思是两个unsigned long long
,应该变为II
,这意味着两个unsigned int
s
2:位于Snow Leopard上:/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/Foundation/PyObjC.bridgesupport