37 votes

Pouvez-vous implémenter manuellement les liaisons Cocoa?

J'ai eu une fissure à la mise en œuvre de liaisons pour mon propre NSView sous-classe. Il fonctionne, mais il y a des problèmes avec les conserver cycles lors de la liaison à Propriétaire du Fichier à partir d'un fichier nib. Après avoir lu dans un peu, j'ai découvert qu'Apple avait le même problème quelques années en arrière, mais ont fixé avec de la magie sans-papiers de la classe (NSAutounbinder).

Il y a une longue discussion de la conserver cycle de problème ici http://www.cocoabuilder.com/archive/message/cocoa/2004/6/12/109600 . La solution de contournement consiste à séparer toutes les liaisons avant de la fenêtre contrôleur est sorti, pas avant qu'il soit libéré, dans un endroit comme windowWillClose:. Cela me semble inutile de faire des hack pour moi.

Ma question est la suivante: Est-il possible de faire des liaisons personnalisées qui fonctionnent ainsi que celles faites par Apple, sans l'aide de fonctionnalités non documentées? Je suis aller sur ce de la mauvaise façon?


Mise à JOUR 2: j'ai trouvé une solution qui permet de manuellement la mise en œuvre des liaisons de travailler exactement comme Apple liaisons. Il prend le parti des sans-papiers NSAutounbinder classe, sans utilisation de fonctions non documentées. Je vais poster la solution plus tard aujourd'hui.


Mise à JOUR: j'ai essayé à l'aide d' exposeBinding:, et il ne semble pas faire de différence. Cependant, l' NSObject de la mise en œuvre de l' bind:toObject:withKeyPath:options: de la moitié des œuvres. Elle se propage changements de bindee de liant (c'est à dire à partir du modèle/contrôleur de vue), mais ne fonctionne pas de la manière opposée. Aussi, bien que le bindee est évidemment d'être observé, observeValueForKeyPath:ofObject:change:context: n'est jamais déclenché.

Exemple de projet ici: http://www.tomdalling.com/wp-content/BindingsTest.zip

La documentation d'Apple indique que vous n'avez, en fait, ont pour remplacer bind:toObject:withKeyPath:options: pour mettre en œuvre le manuel de liaisons. Voir ici: http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Concepts/HowDoBindingsWork.html


NOTE de CÔTÉ: j'ai étudié la façon dont les sans-papiers NSAutounbinder œuvres, et voici ce que je sais.

Lors de la création d'une liaison à un NSWindowController, l'objet lié est en fait un NSAutounbinder qui est acquis à partir de la NSWindowController avec -[NSWindowController _autounbinder]. NSAutounbinder est un non-conservation de proxy pour le NSWindowController objet. Il est non-retenue pour éviter de le conserver cycle de problème.

Quand -[NSWindowController de presse] est appelé et retainCount == 1, La NSAutounbinder délie toutes les liaisons à lui-même. Cela garantit qu'il n'existe pas en balançant des pointeurs de l'objet avant qu'il soit libéré.

22voto

Tom Dalling Points 10656

Ici est la meilleure solution que je peux trouver. J'ai une discussion plus détaillée et le code de démonstration ici: http://tomdalling.com/blog/cocoa/implementing-your-own-cocoa-bindings/

Fondamentalement, vous NE PAS écraser bind:toObject:withKeyPath:options: ou unbind:. L'implémentation par défaut sur NSObject utilisera NSAutounbinder afin d'éviter de conserver des cycles. Louis Gerbarg l'a souligné, il existe encore des situations où l' NSAutounbinder n'est pas un coup de pied dans. Cependant, vous pouvez obtenir de vos fixations de travail au moins aussi bien que Apple liaisons.

Parce que l'implémentation par défaut de bind:toObject:withKeyPath:options: ne met pas à jour le modèle lorsque les changements de vue, vue axés sur les changements doivent être appliquées manuellement. Vous pouvez utiliser -[NSObject infoForBinding:] pour obtenir toutes les informations nécessaires pour mettre à jour l'objet lié. J'ai ajouté ma propre méthode sur NSObject avec une catégorie:

-(void)propagateValue:(id)value forBinding:(NSString*)binding;

Il gère l'obtention de l'objet lié, lié à clé, et en appliquant à la valeur du transformateur. La mise en œuvre est disponible à partir du lien en haut.

3voto

Louis Gerbarg Points 33025

La réponse courte est non, vous ne pouvez pas l'obtenir pour fonctionner avec aucune solution de contournement dans le code appelant et des plumes. Même NSAutounbinder manque certains cas, pour le NSDocument et NSWindowController, si Apple ne peut pas le faire fonctionner correctement pour 2 classes, ils spécialement monter ceux d'entre nous sans accès aux entrailles de AppKit ont aucune chance.

Cela dit, il y a deux solution de contournement qui sont peut-être un peu plus agréable que de déliaison dans windowWillClose:.

  1. Ne se lie pas au Propriétaire du Fichier, mais au lieu de faire glisser un NSObjectController comme au niveau de la racine de l'objet dans la plume et le lier à cela, alors setContents: sur l'objet de contrôleur au cours de awakeFromNib.
  2. Tournez sur la Collecte des Ordures. Si c'est une option qu'il résout tous l'objet de questions de cycle ;-) Évidemment GC présente ses propres problèmes, et si vous avez besoin de 10,4 compatibilité, il est un non-starter.

3voto

Justin Williams Points 363

Voir mmalc de GraphicsBindings exemple pour un bon exemple de comment implémenter votre propre liaisons. Vous avez besoin de mettre en œuvre la NSKeyValueBindingCreation informel protocole pour qu'il fonctionne. Pour permettre à vos contrôleurs sais qu'il y a des choses qui peuvent être liés, appel exposeBinding dans l' + (id)de la méthode initialize de votre point de vue:

+ (void)initialize { [self exposeBinding:@"ILIKEBINDAGE"]; }

Vous aurez alors besoin de mettre en œuvre chacune des liaisons de méthodes de gestion dans le NSKeyValueBindingCreation protocole. En gros, vous avez besoin pour l'installation de KVO de la vue, de sorte qu'il sait quand la mise à jour basée sur l'application de comportements et de gérer le nettoyage (unbind:).

C'est beaucoup d'extra, assez laid code de sorte qu'il se peut que l'utilisation traditionnelle de la colle le code, il fonctionne mieux et est plus facile à lire.

2voto

Ryan Ballantyne Points 1462

Vous voudrez peut-être consulter le protocole NSKeyValueBindingCreation . Il vous permet de créer des liaisons par programmation via du code. (N'oubliez pas de faire le travail dans une méthode awakeFromNib si vous devez référencer des variables IBOutlet ou si elles peuvent être nulles.)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X