2010-11-26 2 views
52

Kann jemand in einfachen Worten erklären, was ist Key-Value-Coding und Key-Value-Observing? Bitte geben Sie keine Links zum Referenzdokument von Apple Developer an. Ich bin durch sie gegangen. Ich erwarte eine Erklärung in sehr einfachen Worten.Was ist Schlüssel-Wert-Kodierung und Schlüssel-Wert-Beobachtung in Ziel C?

+0

Dies ist das beste dafür .. http://www.slideshare.net/sergio.acosta/intro-to-cocoa-kvckvo-and-bindings-presentation – iPatel

Antwort

96

Key-Value-Codierung (KVC) bedeutet Zugriff auf eine Eigenschaft oder einen Wert mithilfe einer Zeichenfolge.

id someValue = [myObject valueForKeyPath:@"foo.bar.baz"]; 

, die die gleiche wie sein könnte:

id someValue = [[[myObject foo] bar] baz]; 

Key-Value Observing (KVO) können Sie Änderungen an einer Eigenschaft oder Wert beobachten.

Um eine Eigenschaft mit KVO zu beobachten, würden Sie eine Eigenschaft mit einer Zeichenfolge identifizieren; d.h. unter Verwendung von KVC. Daher muss das beobachtbare Objekt KVC-konform sein.

[myObject addObserver:self forKeyPath:@"foo.bar.baz" options:0 context:NULL]; 
+2

Ist das das gleiche "Darren" wie oben? LOL –

+2

@Jacob Relkin Einer der Darrens sollte 'darren * darrenB = & darrenA;' sein :) – alex

+0

Nein, aber es sieht so aus, als wären wir beide aus der gleichen Stadt und beantworten dieselben Fragen zur gleichen Zeit ... Was? sind die Chancen? – Darren

26

Schlüsselwert Codierung greift einfach auf eine Eigenschaft eines Objekts über eine Zeichenfolge anstelle der Literalsyntax zu.

Die Stärke von KVC ist, dass Sie zur Laufzeit beliebige Zeichenfolgen angeben können (das könnte natürlich auch sehr gefährlich sein).

+5

Hallo, könnten Sie bitte dieses eine Finale ausfüllen Schritt - Ich verstehe die "Kraft" von KVC noch nicht. Ich verstehe, dass ich sagen konnte [carObject valueForKeyPath: @ "changePriceToFree"], aber diese Eigenschaft (changePriceToFree) muss bereits existieren, damit ich KVC verwenden kann. Warum also nicht einfach die Immobilie anrufen? Ich verstehe, dass ich den Schlüssel, den ich in meinem Code zur Laufzeit anrufe, variieren kann, aber ich weiß immer noch nicht, wie ich diese Tatsache im wirklichen Leben anwenden könnte. Ich gehe davon aus, dass dies ein Kernthema ist, das IOS-Entwickler kennen sollten. Vielen Dank! – user798719

+0

Dies ist eine hervorragende Erklärung. Allerdings würde ich auch die Frage von Benutzer798719, warum KVC so mächtig ist, und warum würde dies anstelle des Aufrufs der Eigenschaft mit Literal-oder Punkt-Notation verwendet echo? Vielen Dank! – daspianist

+5

@ user798719 (und @daspianist), stellen Sie sich vor, Sie haben eine Datenbank, in der Sie Ihre Objective-C-Objekte gespeichert haben. Sie müssen nun ein Objekt abrufen. Anstatt jedes Feld manuell zu erfassen und manuell über die Punkt- oder Literalsyntax im neuen Objekt zu speichern, können Sie jedes Feld in der Datenbank durchlaufen und setValue: ForKey: auf dem Objekt aufrufen. Bsp .: Sie haben ein Objekt "Person" mit den Eigenschaften "Name" und "Bio". Ihre Datenbank hat die Felder "Name" und "Bio". Da die Namen identisch sind, können Sie die Datenbankfelder durchlaufen und setValue: ForKey: (mit Feldname) auf einem neuen "Person" -Objekt aufrufen. – tjklemz

6

Start here.

Key-Wert-Codierung ist ein Mechanismus zum Eigenschaften eines Objekts Zugriff indirekt Strings Eigenschaften zu identifizieren, anstatt durch Aufruf einer Accessormethode oder sie zugreifen direkt durch Instanzvariablen.

+7

Von der ursprünglichen Frage "Bitte stellen Sie keine Links zum Referenzdokument von Apple Developer bereit." –

12

Key-Wert Codierung ermöglicht es Ihnen, eine Eigenschaft eines Objekts zu holen oder zu ändern, um eine Zeichenfolge, zur Laufzeit mit, statt der Notwendigkeit, Code zu schreiben, die auf eine feste Eigenschaft von Anfang zusammengestellt:

NSNumber* foo = [myPopup valueForKey: @"selectedItemIndex"]; 
[myPopup setValue: @15 forKey: @"selectedItemIndex"]; 

Ein gutes Beispiel dafür ist NSTableView auf Mac, wo Sie einfach eine Kennung für jede Tabellenspalte, die der Eigenschaft Ihres Modellobjekts entspricht, die es anzeigen sollte, festlegen und dann ruft Ihre Datenquelle nur -valueForKey:/- setValue: forKey : mit dem Bezeichner der Spalte als Schlüssel und die Werte zeigen sich ziemlich selbst an. Sie fügen nur die richtigen Spalten zur Tabellenansicht in der XIB hinzu.

Die Schlüsselwertüberwachung wurde anschließend hinzugefügt und ermöglicht die Registrierung, um über Änderungen an einem anderen Objekt benachrichtigt zu werden. Sie registrieren Sie sich, indem Sie:

void* gMyKVOContext = &gMyKVOContext; // global variable somewhere that guarantees us a unique address that doesn't collide with a subclass's registration for observing the same property 

... 

[interestingObject addObserver: interestedObject forKeyPath: @"interestingProperty" options: 0 context: gMyKVOContext]; 

Wenn diese Eigenschaft geändert wird, -observeValueForKeyPath: ofObject: Änderung: Kontext: auf dem Objekt aufgerufen werden Sie als Beobachter angegeben. So würden Sie das implementieren wie:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{ 
    if(context == gMyKVOContext && [keyPath isEqualToString: @"interestingProperty"]) 
    { 
     // Update UI that shows interestingProperty 
    } 
    else 
     [super observeValueForKeyPath: keyPath ofObject: object change: change context: context]; 
} 

Der Vorteil hier ist, dass Sie live den Moment aufgerufen werden, dass andere Eigenschaft geändert wird. Beachten Sie, dass Objekte etwas arbeiten müssen, damit diese Benachrichtigungen gesendet werden, sodass nicht alle Eigenschaften als Schlüsselwert beobachtbar sind.Beachten Sie außerdem, dass sich einige Objekte möglicherweise in einem ungültigen Zustand befinden, wenn zwei verwandte Eigenschaften direkt hintereinander geändert werden: Sie werden benachrichtigt, nachdem die erste Eigenschaft geändert wurde, was jetzt der zweiten widerspricht. Erst dann wird die zweite Eigenschaft geändert und Sie " dafür zur Kenntnis genommen. Während dieses Rückrufs des ersten Beobachters kann sich das Objekt in einem seltsamen Zustand befinden, seien Sie also vorsichtig, wie Sie darauf reagieren.

Um eine Eigenschaft beobachtbar zu machen, verwenden Sie entweder die Standardimplementierung @synthesized, wenn Sie es definieren, oder wenn Sie es selbst definieren, implementieren die Setter wie:

-(void) setFoo: (int)inFoo 
{ 
    [self willChangeValueForKey: @"foo"]; 
    _foo = inFoo; 
    [self didChangeValueForKey: @"foo"]; 
} 

Dann immer der Setter durchlaufen, es zu ändern Ändere _foo nicht direkt. Wenn Sie verwandte Eigenschaften haben, die sich wie oben beschrieben widersprechen können, sollten Sie sie beide immer paarweise ändern (Sie können KVC aber nicht verwenden). Um das zu tun, implementieren einen kombinierte Setter wie:

-(void) setFoo: (int)inFoo bar: (int)inBar 
{ 
    [self willChangeValueForKey: @"foo"]; 
    [self willChangeValueForKey: @"bar"]; 
    _foo = inFoo; 
    _bar = inBar; 
    [self didChangeValueForKey: @"bar"]; 
    [self didChangeValueForKey: @"foo"]; 
} 

Auf diese Weise beiden Meldungen gesendet werden, während die Eigenschaften in der richtigen Zuständen sind.