2012-01-12 1 views
2

Lorsque je me lie à un keypath à plusieurs niveaux, par exemple objectValue.person.photo, il ne se met pas à jour lorsque la personne change, uniquement lorsque la photo change. Cela semblerait être un problème avec seulement la dernière clé du chemin observée pour les changements.Liaisons multicouche de cacao

Est-il possible d'observer plusieurs niveaux de liaisons? Par exemple, dans SproutCore, si vous placez un astérisque dans le chemin, tout ce qui suit sera observé pour les changements (objectValue*person.photo).

Répondre

2

Si vos fixations sont pas mises à jour lorsque objectValue.person est modifiée, cela signifie généralement que tout objet est en objectValue est sans valeur clé d'observation conforme à la person. clé avec des objets correctement mis en œuvre, des mutations non-feuilles le long d'un travail KeyPath bien . Par exemple, à partir de la base non-modèle de document cacao application, je cuisinais l'exemple suivant:

tête:

@interface Person : NSObject 
@property (copy) NSString* name; 
@end 

@interface Car : NSObject 
@property (retain) Person* driver; 
@end 

@interface SOAppDelegate : NSObject <NSApplicationDelegate> 

@property (assign) IBOutlet NSWindow *window; 
@property (retain) Car* car; 

- (IBAction)replaceCar:(id)sender; 
- (IBAction)replaceDriver:(id)sender; 
- (IBAction)changeName:(id)sender; 

@end 

Mise en œuvre:

@implementation Person 
@synthesize name; 
@end 

@implementation Car 
@synthesize driver; 
@end 

@implementation SOAppDelegate 
@synthesize car = _car; 
@synthesize window = _window; 

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification 
{ 
    Person* person = [[[Person alloc] init] autorelease]; 
    person.name = @"Default Name"; 
    Car* car = [[[Car alloc] init] autorelease]; 
    car.driver = person; 
    self.car = car; 
} 

- (IBAction)replaceCar:(id)sender 
{ 
    Person* person = [[[Person alloc] init] autorelease]; 
    person.name = @"Replaced Car"; 
    Car* newCar = [[[Car alloc] init] autorelease]; 
    newCar.driver = person;  
    self.car = newCar; 
} 

- (IBAction)replaceDriver:(id)sender 
{ 
    Person* person = [[[Person alloc] init] autorelease]; 
    person.name = @"Replaced Driver";  
    self.car.driver = person; 
} 

- (IBAction)changeName:(id)sender 
{ 
    self.car.driver.name = @"Changed Name"; 
} 

@end 

Ensuite, dans le .xib, je ajouté trois boutons, appelant chacune des IBActions et ajouté un label dont la propriété value était liée à App Delegate avec un keyPath de car.driver.name

Si vous appuyez sur l'un des boutons, l'étiquette liée sera mise à jour, en dépit du fait que l'un d'entre eux modifie réellement la valeur exacte pointée par les raccourcis keyPath (car.driver.name). La conformité KVO est offerte gratuitement avec les propriétés standard synthétisées, donc nous obtenons des mises à jour appropriées, peu importe le niveau dans le keyPath d'où elles viennent. En bref, les liaisons fonctionnent comme vous le souhaitez (c'est-à-dire qu'elles sont mises à jour pour les modifications apportées aux clés de nœud non feuille dans un keyPath composé). Il y a quelque chose dans l'implémentation des objets dans objectValue ou person qui est déficient et qui empêche cela de fonctionner. Je regarderais là-bas.

Notez également, dans le cas où l'une de ces choses est une collection, que l'observation d'une collection n'est pas la même chose que l'observation de tous les objets d'une collection. Voir this page pour plus d'informations à ce sujet. PS: Oui, je sais que l'exemple fuit la mémoire. Vous pouvez imaginer les méthodes pertinentes -dealloc pour vous-même.