2010-05-20 5 views
1

Mon interface utilisateur ne se met pas à jour lorsque je le souhaite. L'application affiche "projets" en utilisant une vue similaire à iTunes - une liste de sources sur la gauche vous permet de filtrer une liste (NSTableView) sur la droite. Mes filtres se mettent à jour correctement lorsqu'ils examinent un champ simple (comme un nom, une chaîne), mais pas pour des tableaux (comme des balises). Je supprime une balise d'un de mes objets (à partir d'un champ NSMutableArray appelé "balises") et je m'attends à ce qu'elle disparaisse de la liste car elle ne correspond plus au prédicat lié à NSArrayController de ma table.en utilisant KVO pour mettre à jour un NSTableView filtré par un NSPredicate

ProjectBrowser.mm:

self.filter = [NSPredicate predicateWithFormat:@"%@ IN %K", 
               selectedTag, 
               @"tags"]; 

Project.mm:

[self willChangeValueForKey:@"tags"]; 
[tags removeAllObjects]; 
[self didChangeValueForKey:@"tags"]; 

J'ai aussi essayé, mais le résultat est le même:

[[self mutableArrayValueForKey:@"tags"] removeAllObjects]; 

configuration Interface Builder :

  • un objet ProjectBrowser est a son tableau de contenu lié à « du propriétaire du fichier » .projects
  • le prédicat de filtre de contrôleur du projet est lié à « propriétaire du fichier » .filter
  • du fichier Propriétaire
  • un NSArrayController (Project Controller) le XIB La colonne NSTableView est liée à "Project Controller" .name

Répondre

2

J'ai trouvé dans la documentation (KVC Compliance - Dependent Values):

Important: Notez que vous ne pouvez pas configurer dépendances à-plusieurs. Par exemple, supposons que vous ayez un objet Order avec une relation to-many (orderItems) à une collection d'objets OrderItem et les objets OrderItem ont un attribut de prix. Vous souhaitez que l'objet Order ait un attribut total total qui soit en fonction du prix de tous les objets OrderItem dans la relation. Vous ne pouvez pas le faire en implémentant keyPathsForValuesAffectingValueForKey: et en renvoyant orderItems.price en tant que keypath pour totalPrice.Vous devez observer l'attribut de prix de chacun des objets OrderItem dans la collection orderItems et répondre aux changements dans leurs valeurs en mettant à jour vous-même.

Vous ne pouvez pas compter sur les dépendances ou les notifications KVO quand il y a un à plusieurs dans le keypath. Cela s'applique à mon tableau de tags, j'ai donc ajouté du code pour patcher ce lien cassé.

Lorsque j'ajoute un projet à l'ensemble des "projets":

[newProject addObserver:self forKeyPath:@"tags" options:NSKeyValueObservingOptionNew context:nil]; 

Et la partie importante:

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if ([object isKindOfClass:[CProject class]] && [keyPath isEqualToString:@"tags"]) 
    { 
     [self willChangeValueForKey:@"projects"]; 
     [self didChangeValueForKey:@"projects"]; 
    } 
} 

Et pour le nettoyage, lorsque je retire un projet:

[project removeObserver:self forKeyPath:@"tags"]; 

Je ne sais pas si c'est la meilleure solution, mais elle maintient ma liste à jour.

0

Je suis assez surpris que votre premier extrait de code compile même. Il a également peut pas tout à fait le travail que vous attendez parce

self.property = foo; 

est le sucre syntaxique pour

[auto setProperty: foo]; De toute façon, votre problème peut être que vous n'observez pas tags. Je ne suis pas sûr qu'un prédicat observe automatiquement les clés dans sa chaîne de requête.

+0

Merci d'avoir signalé l'erreur de syntaxe, elle s'est produite lors de ma tentative d'extraction du code pertinent. Je l'ai corrigé ci-dessus. – KingRufus

+0

Je n'observe pas les balises, mais le prédicat semble observer des champs simples en cas de besoin. Ce filtre met à jour la liste chaque fois que le nom change: [.. predicateWithFormat: @ "% K ==% @", @ "name", selectedName] Donc si je ne propage pas la notification de changement, malgré mes efforts, comment Je répare ça? La capacité de KVO à observer en utilisant des keypaths comme "project.someObject.someField" me porte à croire que ces changements devraient "remonter" à un observateur sans exiger de code de colle à chaque lien dans la chaîne/le chemin. Actuellement, les tableaux cassent n'importe quelle chaîne dans la fonctionnalité d'observation keypath de mon code. – KingRufus

+0

Une autre supposition: il se peut que le prédicat optimise votre changement parce que vous ne changez pas l'objet de tags lui-même. Essayez '[release tags]; tags = [[NSMutableArray alloc] init]; 'au lieu de' [tags removeAllObjects] ' – JeremyP

Questions connexes