2010-11-10 22 views
2

-setPrimitiveValue:forKey: ne déclenchera pas les notifications KVO. Mais dans mon cerveau, le KVO n'a de sens que lorsque quelque chose change. Mais comment changer quelque chose quand je n'y accède que pour lire?Quel est le point de -primitiveValueForKey :?

-primitiveValueForKey: obtient uniquement l'objet pour une clé. Mais cela ne le modifiera pas. Alors pourquoi/cela pourrait-il causer des notifications KVO lors de l'utilisation de -valueForKey:?

(Bien sûr, il y a un point, mais je ne vois pas encore.)

+1

Veuillez cocher les réponses aux questions, ou s'il y a quelque chose que vous ne comprenez pas, veuillez le demander dans les commentaires sur les réponses. Merci! –

Répondre

23

Les méthodes -primitiveValueForKey: et -setPrimitiveValue:forKey: sont principalement utilisés par Core Data. En particulier, les données de base n'ont pas seulement besoin de savoir quand vous allez modifier un attribut; il a besoin de savoir quand vous allez y accéder aussi, donc il peut implémenter des erreurs.

Ainsi, les données de base ajoutent -{will,did}AccessValueForKey: méthodes à utiliser dans les getters, tout comme les méthodes -{will,did}ChangeValueForKey: existent pour être utilisées par les setters comme agencements de KVO.

Toutefois, il existe une autre difficulté: Core Data gère également le stockage sous-jacent des propriétés modélisées pour vous. Donc, vous avez besoin d'un moyen de manipuler ce stockage sous-jacente au sein de les barrières établies par les méthodes -{will,did}{Access,Change}ValueForKey:. C'est là -primitiveValueForKey: et -setPrimitiveValue:forKey: viennent dans

Voilà pourquoi le modèle standard pour la mise en œuvre des accesseurs de base de données, avant l'existence de @property et @dynamic, ressemblait à ceci:.

// Person.m 
#import "Person.h" 

@implementation Person 

- (NSString *)name { 
    [self willAccessValueForKey:@"name"]; 
    NSString *value = [self primitiveValueForKey:@"name"]; 
    [self didAccessValueForKey:@"name"]; 
} 

- (void)setName:(NSString *)value { 
    [self willChangeValueForKey:@"name"]; 
    [self setPrimitiveValue:value forKey:@"name"]; 
    [self didChangeValueForKey:@"name"]; 
} 

@end 

Maintenant, bien sûr, vous pouvez simplement déclarer une propriété et le définir comme @dynamic si vous voulez de base de données pour générer ce genre de choses pour vous lors de l'exécution:

// Person.h 
@interface Person : NSManagedObject 
@property (nonatomic, readwrite, copy) NSString *name; 
@end 

// Person.m 
#import "Person.h" 

@implementation Person 
@dynamic name; 
@end 

il y a une place ations mais où vous voulez toujours manipuler le stockage sous-jacent sans KVO ou défaut-tirant, cependant. Ainsi, les données de base fournit une nouvelle façon d'obtenir à cela aussi, a également construit autour des déclarations de propriété et synthèse automatique:

// Person.h 
@interface Person : NSManagedObject 
@property (nonatomic, readwrite, copy) NSString *name; 
@end 

// Person.m 
#import "Person.h" 

@interface Person() 
@property (nonatomic, readwrite, copy) NSString *primitiveName; 
@end 

@implementation Person 
@dynamic name; 
@dynamic primitiveName; 
@end 

Notez que je mets la continuation de la classe dans le fichier .m; ce n'est pas quelque chose que le code en dehors de la personne (ou même du code en dehors de -awakeFromInsert et -awakeFromFetch) devrait toucher. Mais cela me permet d'obtenir le stockage sous-jacent pour la propriété "name" sans incorporer les chaînes littérales dans mon code, et avec l'utilisation des types réels.