Cómo entender el principio KVO de la programación Objective-C
KVO (Key Value Observation) es una implementación básica del patrón de observador.
Los principios de KVO
En resumen:
1. Cuando un objeto tiene un observador, cree dinámicamente una subclase de la clase del objeto.
2. Para cada propiedad observada, anule su método establecido.
3. Llame a -willChangeValueForKey: y -didChangeValueForKey: en el método set anulado para notificar al observador.
4. Cuando el atributo no tiene punto de observación, elimine el método anulado.
5. Cuando ningún observador observe ninguna propiedad, elimine la subclase creada dinámicamente.
Charla vacía, verificación simple.
@ interfaz Sark:ns objeto @ propiedad (no atómica, copia) ns cadena * nombre; @ end @implement Sark @end
Sark * Sark = [Sark nuevo] // Punto de interrupción 1 [sark agregar observador:self para ruta clave:@ " nombre " opciones:nskeyvalueobservingoptions nuevo contexto:nil]; // Punto de interrupción 2 sark.name = @ "SasaSa "; ]; //Después del punto de interrupción 3, use -Class y object_getClass() para escribir la clase y la clase real del objeto sark respectivamente.
//Punto de interrupción 1(lldb)po Sark . clase Sark(lldb)po objeto _ getClass(Sark)Sark//Punto de interrupción 2(lldb)po Sark .clase Sark(lldb)po objeto _ getClass(. Sark)nskvonofting_Sark//Punto de interrupción 3 (lldb) posark. classsark(lldb)po object_getclass(sark)sark Los resultados anteriores muestran que cuando se observa un objeto Sark, el marco utiliza el tiempo de ejecución para crear dinámicamente una subclase de la clase Sark nskvonotifying_Sark Para ocultar este comportamiento, nskvonotifying_Sark anula el método de clase para devolver. a la clase anterior como si nada hubiera pasado. Pero queda expuesto cuando se usa object_getClass(), porque este método devuelve el puntero isa de este objeto, y este puntero debe apuntar a un objeto de clase de este objeto.
Entonces echemos un vistazo a la implementación de esta clase dinámica. Cree una extensión NSObject + DL Insight aquí, que encapsule métodos de depuración comunes, como imprimir una clase, atributo, protocolo, etc., para que quede claro de un vistazo.
@ interfaz ns objeto(DLIntrospection)+(NSArray *) clase; + (NSArray *) variables de instancia; métodos; + (NSArray *) protocolo; + (ns diccionario *) descripción para Protocolo: (Protocol *) proto; + (ns cadena *) parentClassHierarchy; @end
Luego continúe en el punto de interrupción:
//Punto de interrupción 1(lldb)po[object_getClass(sark)métodos de instancia]<__NSArrayI 0x8e9aa00>(- (void)setName:(id)arg0,- (void).cxx_destruct,-(id)name ) //Punto de interrupción 2(lldb)po[object_getClass(sark)métodos de instancia]<__NSArrayI 0x8d55870>(-(void)setName:(id) arg0, - (class)class, - (void)dealloc, - (BOOL)_isKVOA ) // punto de interrupción 3 (lldb)po [métodos de instancia object_getClass(sark)]<__ NSArrayI 0 x8e 9 CFF 0 & gt; (- (void)setName: (id)arg0, - (void).cxx_destruct, - ( id)nombre)
Es decir, este método en arco es responsable de completar todas las llamadas a dealloc. Liberar todas las variables. Por supuesto, esto no tiene nada que ver con KVO, así que volvamos al tema.
Como se puede ver en el punto de interrupción 2 anterior, la clase dinámica anula cuatro métodos:
1, -setName: el método principal anulado, que llama a la función de notificación al establecer el valor.
2.-La clase oculta sus propias necesidades y vuelve a la clase original.
3.-Dilock limpia la escena del crimen.
4.-_isKVOA Este es un flag interno. Determina si KVO subclasifica dinámicamente esta clase.
A continuación, verifique si KVO llama a -willChangeValueForKey: y -didChangeValueForKey:
El método de verificación más directo es anular estos dos métodos en la clase Sark:
@ implementación Sark-(void)willChangeValueForKey:(ns string *)key { NSLog(@"% @",nsstringfromcselector(_ cmd));[super willChangeValueForKey:key];}-(void)didChangeValueForKey:(ns string *) clave { NSLog(@"% @", nsstringfromcselector(_ cmd)); [super didChangeValueForKey:key] } @End