3

KVC ガイドに従って、モデル クラスのインデックス付きアクセサー メソッドを 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がすべてのドキュメントを移動した後、私は最終的に型エンコーディングの参照を見つけました。それを読んだ後、私はこれを試しました:

@objc.signature('v@:N^@@')
def getFoos_range_(self, buf, range):

しかし、これもうまくいかないようでした。最初の引数は C 配列へのポインターであるはずですが、長さは実行時まで不明であるため、正しい型エンコーディングを構築する方法が正確にはわかりませんでした。私は'v@:N^[1000@]@'ただ見ようとしましたが、それもうまくいきませんでした。

モデル オブジェクトは、テーブル ビューを駆動する NSArrayController の contentArray にバインドされています。おそらく、ブリッジが提供している署名とは異なる署名を期待しているため、このメソッドをまったく呼び出していないようです。助言がありますか?

4

1 に答える 1

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仕事)。私はまだこれらのビットを理解していません。

このメタデータNSArray getObjects:range:は Foundation PyObjC.bridgesupport ファイル2のメタデータに基づいており、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 では、 2 つのQQを意味する は、2 つのを意味するunsigned long longになります。 2: (Snow Leopard では) 次の場所にあります。 /PyObjC/財団/PyObjC.bridgesupportIIunsigned int

于 2011-03-17T08:54:04.907 に答える