Key-Value-Coding ist ein elementares und grundlegendes Design-Pattern von Cocoa.
Accessors
Im Prinzip ist damit ein System von Accessoren gemeint. Am Beispiel wird das einfach deutlich. Nehmen wir an, eine Klasse hat eine iVar (Instanzvariable) und Property "NSString* myName":
In Cocoa wird üblicherweise außerhalb der Klasse niemals direkt auf eine Instanzvariable zugegriffen. Jede Klasse stellt hierfür sogenannte Accessoren zur Verfügung, also jeweils eine Getter- und eine Setter-Methode, z.B.:
-(NSString*)name { return name; }
-(void)setName:(NSString*)newName {
if(newName != name) {
[name release];
name = [newName copy];
}
}
@Properties = Accessors
Der Einsatz von Properties erleichtert lediglich das Tippen, da hiermit die Accessoren beim Kompilieren automatisch erstellt werden:
// MyFile.h
@property(nonatomic, copy) NSString* name;
// MyFile.m
@synthesize name;
Durch @synthesize werden also die beiden o.g. Methoden generiert und dabei auf das Memory Management Rücksicht genommen.
Using Accessors
Gibt es diese Accessoren, können die Werte wie folgt gelesen/gesetzt werden. Jede dieser Methoden (außer die letzte) ist gültig und macht exakt das Gleiche:
// getter
NSString *myString;
myString = [self name];
myString = [self valueForKey:@"name"];
myString = self.name;
myString = name; // ACHTUNG: hier wird direkt auf die iVar und nicht auf den Getter zugegriffen!!!
// setter
[self setName:@"Test"];
[self setValue:@"Test" forKey:@"name"];
self.name = @"Test";
name = @"Test"; // ACHTUNG: hier wird direkt auf die iVar und nicht auf den Setter zugegriffen!!!
Man beachte, dass die mit "ACHTUNG" versehenen Zeilen nicht auf die Getter/Setter, sondern direkt auf die Instanzvariablen zugreifen. Damit wird u.a. auch das Memory Management (retain/release-Zyklen) umgangen, was natürlich schlecht ist ;-)
Key/Value
Key-Value-Coding meint also ganz allgemein, das Zur-Verfügung-Stellen von Accessoren für Properties. Anders ausgedrückt, hat die Klasse verschiedene Eigenschaften ("Properties"), auf deren Werte ("Values") man mit Schlüsselwörtern ("Keys") zugreifen kann. Oder einfacher: jede Property kann mit einem valueForKey: und setValue:forKey: Selektor adressiert werden, ohne dass man die Klasse, mit der man kommuniziert, importieren muss.
// ohne key-value coding:
NSString* myString = [myObject name];
[myObject setName:@"Hallo Welt"];
// mit key-value coding:
NSString* myString = [myObject valueForKey:@"name"];
[myObject setValue:@"Hallo Welt" forKey:@"name"];
// collections benutzen Key-Value-Coding
NSNumber* myNumber = [myDict valueForKey:@"myNumber"];
[myDict setValue:[NSNumber numberWithInt:5] forKey:@"myNumber"];
Vorteile von Key-Value-Coding
- Keine benannten Selektoren (nur valueForKey: und setValue:forKey:)
- Sämtliche Cocoa-Collections (NSArray, NSDictionary...) benutzen KVC
- Bindings (nicht verfügbar in iPhone OS <= 3.0) funktionieren mit KVC
- Ideal für dynamisch synthetisierte Methoden
Key-Value-Observing
KVO (Key-Value-Observing) ist ein sehr schlaues Konzept zur Beobachtung von geänderten Properties. Das Funktionsprinzip ist einfach:
- Registrieren, um Benachrichtigungen bei Änderungen von Properties zu erhalten
- Methode überschreiben, die den Empfang von Nachrichten bei Änderungen erlaubt
- Registrierung entfernen, wenn keine Beobachtung mehr erwünscht ist
// register for KVO (eg. in -viewDidLoad:)
[model addObserver:self
forKeyPath:@"propertyName"
options:NSKeyValueObservingOptionNew
context:NULL];
// implement this method to receive notifications
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context
{
NSLog(@"Property changed: %@", object);
}
// remove observer when done (eg. in -dealloc)
[model removeObserver:self forKeyPath:@"propertyName"];
Vorteile von Key-Value-Observing
- Keine Referenz vom Model zum Controller: Der Controller kann Änderungen im Model registrieren, ohne dass das Model eine explizite Referenz zum Controller halten muss
- Vermeiden von unerwünschten Schleifen beim Aktualisieren von Werten
Links
Diese Seite ist Teil des Werkmoduls iOS Development von Michael Markert für Interface Design / Fakultät Medien an der Bauhaus-Universität Weimar.