pyobjc indexed accessor method with range

前端 未结 1 778
臣服心动
臣服心动 2021-01-21 01:34

I\'m trying to implement an indexed accessor method for my model class in Python, as per the KVC guide. I want to use the optional ranged method, to load multiple objects at onc

相关标签:
1条回答
  • 2021-01-21 02:24

    You were close. The correct decorator for this method is:

    @objc.signature('v@:o^@{_NSRange=QQ}')
    

    NSRange is not an object, but a struct, and can't be specified simply as @; you need to include the members1.

    Unfortunately, this is not the end of it. After a whole lot of experimentation and poring over the PyObjC source, I finally figured out that in order to get this method to work, you also need to specify metadata for the method that is redundant to this signature. (However, I still haven't puzzled out why.)

    This is done using the function 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}')
                 }
            )
    )
    

    Examples and some details of the use of this function can be found in the file test_metadata_py.py (and nearby test_metadata*.py files) in the PyObjC source.

    N.B. that the metadata has to be specified on the superclass of whatever class you are interested in implementing get<Key>:range: for, and also that this function needs to be called sometime before the end of your class definition (but either before or inside the class statement itself both seem to work). I haven't yet puzzled these bits out either.

    I based this metadata on the metadata for NSArray getObjects:range: in the Foundation PyObjC.bridgesupport file2, and was aided by referring to Apple's BridgeSupport manpage.

    With this worked out, it's also worth noting that the easiest way to define the method is (at least, 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)
    

    I.e., using your array's built-in getObjects:range:.


    1: On 32-bit Python, the QQ, meaning two unsigned long longs, should become II, meaning two unsigned ints
    2: Located (on Snow Leopard) at: /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/Foundation/PyObjC.bridgesupport

    0 讨论(0)
提交回复
热议问题