Minden Objective-C oktatási anyag már a kezdetek kezdetén tárgyalja a KVO témakört, amely szorosan kapcsolódik a KVC-hez:
Key-value coding is a mechanism for indirectly accessing an object’s attributes and relationships using string identifiers. It underpins or is related to several mechanisms and technologies special to Cocoa programming, among them Core Data, application scriptability, the bindings technology, and the language feature of declared properties. (Scriptability and bindings are specific to Cocoa on OS X.) You can also use key-value coding to simplify your program code.
Az Observer pattern egy elég erőteljesen alkalmazott tervezési minta a Cocoa keretrendszerben. Amikor minden az elvártnak megfelelően működik, olyankor a KVO egy áldás, amely óriási terhet vesz le a fejlesztő válláról:
Key-value observing provides a mechanism that allows objects to be notified of changes to specific properties of other objects. It is particularly useful for communication between model and controller layers in an application. (In OS X, the controller layer binding technology relies heavily on key-value observing.)
Például: megváltozik az egyik objektum valamely tulajdonsága, amelyet az őt figyelő másik objektum észrevesz és ennek következtében frissíti valamely saját tulajdonságát. Ez utóbbit figyeli egy másik observer, amely mondjuk a UI megjelenítéséért felelős. Észreveszi, hogy változás történt a megfigyelt objektumban és frissíti a felületet. Külön kód megírása nélkül, automatikusan. Egy tulajdonság megváltozása értesíti a másik objektumot, amely értesít egy harmadikat stb. és végül a felhasználói felületen megjelenik a változás, mindenféle spagetti kód nélkül. Super simple!
Amikor azonban valami nem úgy működik ahogyan azt a fejlesztő szeretné, olyankor könnyen rémálommá válik az observer pattern használata, mert irtó nehéz nyomon követni, hogy pontosan mi történik a háttérben. Az objektumok üzengetnek egymásnak, ezáltal fel van építve egyfajta logikai riadólánc. Majd egyszer csak “eltörik” valami a kódban és nem frissül a felület, vagy nem az jelenik meg ami elvárt volna. Hol lehet a probléma? Sok fejfájást tud ez okozni, amikor már egy kicsit összetettebb az adatszerkezet.
A minap óriásit szívtam a fent említett példával. Kicsit változott egy adatszerkezet és valahol megszakadt a riadólánc. Egy bizonyos osztályban a KVO kifogástalanul működött, míg ennek a leszármazottjában valami rendellenesség lépett fel és a hozzá kapcsolódó felület nem reprezentálta a változásokat. Az NSKeyValueObserving protokollnak van egy osztálymetódusa, amely automatikusan regisztrál egy (vagy több) observert a paraméterben megadott tulajdonsághoz. Ha a megfigyelt tulajdonságok valamelyike változik, akkor azok automatikusan értesítést küldenek a változásról:
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)keyWhen an observer for the key is registered with an instance of the receiving class, key-value observing itself automatically observes all of the key paths for the same instance, and sends change notifications for the key to the observer when the value for any of those key paths changes.
Bár a megfelelő osztálymetódus létre volt hozva az osztály implementációjában, mégsem történt meg az automatikus KVO. Kis debuggolást követően kiderült, hogy a fent említett osztálymetódus eleve meg sem hívódik, így be sincs regisztrálva a megfelelő observer a tulajdonsághoz. De miért nem hívódik meg az osztálymetódus? Pár órás küzdelem után legyűrt a fáradtság és munkámat végezetlenül hagytam. Reggel ismét nekiültem, hogy kiderítsem a probléma okát. Átolvastam a kapcsolódó dokumentációt és pár percen belül kiszúrtam a nyilvánvalót, amely feketén fehéren le van írva a doksiban: When an observer for the key is registered with an instance of the receiving class …
OMG, egész egyszerűen nem volt regisztrált observer a UI frissítését végző osztályban az adott tulajdonsághoz, így az osztálymetódus meg sem hívódott, így az adott tulajdonság nem frissült automatikusan egy másik tulajdonság függvényében és így állt elő az anomália. A két soros javítás (observer regisztráció és felszabadítás) pár másodpercet vett igénybe és működik minden ahogy annak kell.
Erről beszéltem. Amikor minden az elvártnak megfelelően működik, akkor a KVO rengeteg időt és energiát spórol meg a fejlesztőnek, de az adatszerkezetek változásával ez könnyen megváltozhat, úgyhogy csak ésszel!


