2009-09-03 6 views
3

J'essaie d'implémenter une méthode d'accès indexée pour ma classe de modèle en Python, comme pour the KVC guide. Je veux utiliser la méthode à distance optionnelle, pour charger plusieurs objets à la fois pour des raisons de performance. La méthode prend un pointeur vers un tampon C-array dont ma méthode a besoin pour copier les objets. J'ai essayé quelque chose comme ce qui suit, qui ne fonctionne pas. Comment puis-je accomplir cela?Méthode d'accès indexée pyobjc avec plage

@objc.accessor # i've also tried @objc.signature('[email protected]:o^@') 
def getFoos_range_(self, range): 
    return self._some_array[range.location:range.location + range.length] 

Modifier: Je trouve enfin la type encodings reference après qu'Apple a déplacé tous les documents. Après avoir lu cela, j'ai essayé ceci:

@objc.signature('[email protected]:N^@@') 
def getFoos_range_(self, buf, range): 

mais cela ne semble pas fonctionner non plus. Le premier argument est censé être un pointeur vers un C-array, mais la longueur est inconnue jusqu'à l'exécution, donc je ne savais pas exactement comment construire le codage de type correct. J'ai essayé '[email protected]:N^[[email protected]]@' juste pour voir, et cela n'a pas fonctionné non plus.

Mon objet de modèle est lié à contentArray d'un NSArrayController pilotant une vue tabulaire. Il ne semble pas du tout appeler cette méthode, peut-être parce qu'elle s'attend à une signature différente de celle fournie par le pont. Aucune suggestion?

Répondre

2

Vous étiez proche. Le décorateur correct pour cette méthode est la suivante:

@objc.signature('[email protected]:o^@{_NSRange=QQ}') 

NSRange est pas un objet, mais une structure, et ne peut pas être spécifié simplement comme @; vous devez inclure les membres .

Malheureusement, ce n'est pas la fin de celui-ci. Après beaucoup d'expérimentation sur la source PyObjC, j'ai finalement compris que pour que cette méthode fonctionne, vous devez également spécifier des métadonnées pour la méthode redondante à cette signature. (Cependant, je n'ai pas encore perplexe pourquoi.)

Ceci est fait en utilisant la fonction 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}') 
      } 
     ) 
) 

exemples et quelques détails de l'utilisation de cette fonction se trouvent dans le fichier test_metadata_py.py (et les fichiers test_metadata*.py à proximité) dans la source PyObjC.

N.B. que la métadonnée doit être spécifiée sur superclasse de la classe que vous êtes intéressé à implémenter get<Key>:range: pour, et aussi que cette fonction doit être appelée avant la fin de votre définition de classe (mais avant ou dans l'instruction class lui-même les deux semblent fonctionner). Je n'ai pas encore déconcerté ces bits non plus.

I sur la base de ces métadonnées sur les métadonnées pour NSArray getObjects:range: dans le fichier Fondation PyObjC.bridgesupport , et a été aidé en se référant à Apple BridgeSupport manpage.

Avec cela a fonctionné, il est également intéressant de noter que la meilleure façon de définir la méthode est (au moins, OMI):

@objc.signature('[email protected]:o^@{_NSRange=QQ}') 
def get<#Key#>_range_(self, buf, inRange): 
    #NSLog(u"get<#Key#>") 
    return self.<#Key#>.getObjects_range_(buf, inRange) 

à savoir, en utilisant intégré dans votre tableau getObjects:range:.


1: 32 bits Python, le QQ, ce qui signifie deux unsigned long long s, devrait devenir II, ce qui signifie deux unsigned int s
2: Situé (sur Snow Leopard) à:/Système/Bibliothèque/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/PyObjC/Fondation/PyObjC.bridgesupport

Questions connexes