【问题标题】:pyobjc indexed accessor method with range具有范围的pyobjc索引访问器方法
【发布时间】:2010-11-25 11:26:09
【问题描述】:

我正在尝试根据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。它似乎根本没有调用此方法,可能是因为它期望的签名与桥提供的签名不同。有什么建议吗?

【问题讨论】:

    标签: python cocoa pyobjc key-value-coding


    【解决方案1】:

    你很亲密。此方法的正确装饰器是:

    @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 文件2NSArray 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 longs,应该变成 II,意思是两个 unsigned ints
    2:位于(在雪豹上):/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/Foundation/PyObjC.bridgesupport

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-10
      相关资源
      最近更新 更多