Dacă ați lucrat vreodată cu KVO (Key-Value Observing) în Cocoa, este posibil să fiți diferiți în diverse probleme. Aplicația API nu este grozavă și uitarea pentru eliminarea unui observator poate duce la scurgerea memoriei sau chiar la accidentele mai grave. Biblia KVOController a Facebook își propune să rezolve această problemă.
Dacă sunteți nou la observarea cu valoare cheie sau KVO, vă recomandăm să citiți mai întâi ghidul dezvoltatorului Apple pe această temă sau articolul lui Mattt Thompson despre NSHipster. Pentru a cita ghidul Apple pe KVO, "Observarea valorii cheie oferă un mecanism care permite obiectelor să fie notificate cu privire la modificările anumitor proprietăți ale altor obiecte". Mattt definește KVO după cum urmează: "Key-Value Observing permite introspecția ad-hoc, evented între instanțe specifice de obiecte ascultând pentru modificări pe o anumită cale cheie." Cuvintele cheie sunt evented și calea cheie.
Înainte de a discuta despre biblioteca KVOController, aș dori să fac un moment pentru a explora API-ul KVO.
Nu voi acoperi KVO în detaliu în acest tutorial, dar este important să înțelegeți conceptul de bază al KVO. Ideea este simplă. Un obiect poate asculta modificările anumitor proprietăți ale unui alt obiect. Obiectul observator este adăugat de obiectul țintă ca observator pentru o anumită cale de cheie.
Să ilustrăm acest lucru cu un exemplu. Dacă objectB
dorește să fie notificat atunci când Nume
proprietatea objectA
schimbări, atunci objectA
trebuie să adăugați objectB
ca observator al căii cheie Nume
. Datorită verbozității obiectivului C, codul pentru a realiza acest lucru este destul de simplu.
[objectA addObserver: objectB forKeyPath: @ opțiunile "name": NSKeyValueObservingOptionNew context: NULL];
Oricând objectA
„s Nume
schimbări de proprietate, observeValueForKeyPath: ofObject: schimbare: Context:
este invocată. Primul parametru este calea cheie care este observată de către objectB
, al doilea parametru este obiectul căii cheie, al treilea argument este un dicționar care descrie modificările, iar argumentul final este contextul care a fost trecut ca argument final al addObserver: forKeyPath: opțiuni: Context:
.
Sper că sunteți de acord că acest lucru nu este foarte elegant. Dacă utilizați extensiv KVO, implementarea lui observeValueForKeyPath: ofObject: change: context: rapid devine lungă și complexă.
Este important să nu mai ascultați modificările atunci când un obiect nu mai este interesat să primească notificări pentru o anumită cale cheie. Acest lucru se face invocând removeObserver: forKeyPath:
sau removeObserver: forKeyPath: Context:
.
Problema pe care fiecare dezvoltator o întâmpină într-un anumit moment este fie să uiți să suni removeObserver: forKeyPath:
sau sunând removeObserver: forKeyPath:
cu o cale cheie care nu este observată de către observator. Motivele pentru acest lucru sunt multiple și sunt rădăcina problemei cu care se confruntă mulți dezvoltatori atunci când lucrează cu KVO.
Dacă uitați să invocați removeObserver: forKeyPath:
, este posibil să ajungeți la o scurgere de memorie. Dacă invocați removeObserver: forKeyPath:
iar obiectul nu este înregistrat ca observator, o excepție este aruncată. Cireșul de pe tort este că NSKeyValueObserving
protocolul nu oferă o modalitate de a verifica dacă un obiect observă o anumită cale de cheie.
Din fericire, echipa de cacao de pe Facebook a fost la fel de supărată de problemele de mai sus, așa cum ești și au venit cu o soluție, biblioteca KVOController. În loc să reinventăm roata, echipa de la Facebook a decis să construiască pe partea de sus a KVO. În ciuda neajunsurilor sale, KVO este robustă, susținută pe scară largă și foarte utilă.
Biblioteca KVOController adaugă o serie de lucruri la KVO:
Înainte de a începe, este important să subliniem că biblioteca KVOController necesită ARC și că țintele minime de implementare sunt iOS 6 pentru iOS și 10.7 pentru OS X.
Sunt un mare susținător al CocoaPods și sper că sunteți prea. Pentru a adăuga biblioteca KVOController la un proiect care utilizează CocoaPods, adăugați podul în Podfile-ul proiectului și executați actualizare pod
pentru a instala biblioteca.
pod "KVOController"
Alternativ, puteți descărca ultima versiune a bibliotecii de la GitHub și adăugați manual biblioteca prin copiere KVOController.h și KVOController.m la proiectul dvs..
Primul lucru pe care trebuie să-l faceți este să inițializați o instanță a FBKVOController
clasă. Uitați-vă la următorul fragment de cod în care creez a FBKVOController
instanță într-un controler de vizualizare initWithNibName: pachet:
metodă.
- (id) initWithNibName: (NSString *) pachet nibNameOrNil: (NSBundle *) nibBundleOrNil auto = [super initWithNibName: nibNameOrNil bundle: nibBundleOrNil]; dacă (auto) _KVOController = [FBKVOControllerler controllerWithObserver: self]; întoarce-te;
Rețineți că stochez o referință la FBKVOController
obiect în controlerul de vizualizare _KVOController
variabila de instanta. O caracteristică excelentă a bibliotecii KVOController este aceea că observatorul este înlăturat automat în momentul în care acesta este FBKVOController
obiect este dealocat. Cu alte cuvinte, nu este nevoie să vă amintiți să eliminați observatorul, deoarece acest lucru se face automat în momentul în care se află FBKVOController
obiect este dealocat.
Aveți mai multe opțiuni pentru a începe observarea unui obiect. Puteți lua abordarea tradițională invocând observa: keyPath: opțiuni: Context:
. Rezultatul este că observeValueForKeyPath: ofObject: schimbare: Context:
este invocată ori de câte ori are loc un eveniment de schimbare.
[_KVOController observați: keykeyPath: @ opțiuni "name": NSKeyValueObservingOptionNew context: NULL];
Însă FBKVOController
clasa utilizează de asemenea blocuri și acțiuni personalizate, după cum puteți vedea în următoarele fragmente de cod. Sunt sigur că sunteți de acord că acest lucru face ca lucrul cu KVO să fie mult mai plăcut.
[_KVOController observați: keykeyPath: @ opțiuni "name": NSKeyValueObservingOptionNew bloc: ^ (obser id, id id, NSDictionary * change) // Răspundeți la modificări];
[_KVOController observați: tasta persoanePath: @ opțiunile "nume": NSKeyValueObservingOptionNew action: @selector (nameDidChange :)];
Chiar dacă observatorul este eliminat automat atunci când FBKVOController
obiect este dealocat, adesea este necesar să opriți observarea unui obiect înainte de a fi alocat observatorul. Biblioteca KVOController are o serie de metode pentru a îndeplini această sarcină simplă.
Pentru a opri observarea unei anumite căi cheie a unui obiect, invoca unobserve: keyPath:
și să treacă obiectul și calea cheie. De asemenea, puteți opri observarea unui obiect invocând unobserve:
și treci în obiectul pe care vrei să-l oprești observând. Pentru a opri observarea fiecărui obiect, îl puteți trimite FBKVOController
obiectează un mesaj de unobserveAll
.
Dacă analizați implementarea FBKVOController
, veți observa că păstrează o hartă internă a obiectelor și a căilor cheie observate de observator. FBKVOController
clasa este mai iertator decât punerea în aplicare a Apple de KVO. Dacă spuneți FBKVOController
obiect de a opri observarea unui obiect sau a unei căi cheie pe care nu o observă, nu este aruncată nicio excepție. Așa ar trebui să fie.
Chiar dacă KVO nu este un concept dificil de înțeles, asigurându-vă că observatorii sunt îndepărtați în mod corespunzător și condițiile de rasă nu provoacă haos este adevărata provocare atunci când lucrați cu KVO.
Vă încurajez să aruncați o privire la biblioteca KVOController. Cu toate acestea, vă sfătuiesc să obțineți o bună înțelegere a KVO înainte de ao utiliza în proiectele dvs., astfel încât să știți ce face această bibliotecă pentru dvs. în spatele scenei.