美文网首页
ios KVO原理和实现简易KVO

ios KVO原理和实现简易KVO

作者: songjk | 来源:发表于2019-03-03 14:50 被阅读0次

一内容概述

本文主要分析kvo的底层原理,以及如何自己实现简易kvo。kvo的官方解释:Key-value observing is a mechanism that allows objects to be notified of changes to specified properties of other objects.

二详细步骤

1.ios系统自带kvo实现原理

A.如何使用系统kvo

需求是要控制器要观察属性myBoy中属性name的变化,myBoy为boy类的对象,实现方式如下:

// 添加观察 myBoy添加控制器也就是下面的self为观察者,观察的key为name
[self.myBoy addObserver:self forKeyPath:NSStringFromSelector(@selector(name)) options:NSKeyValueObservingOptionNew context:nil];
//观察回调方法 当myBoy通过.name或者setValue:forKey:方法改变name值时就会调用下面的方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"change:%@",change);
}

B.原理说明

1.当myBoy调用addObserver这个方法之后,系统会创建一个boy的派生类:NSKVONotifying_boy,在该子类中重写观察的属性(name)的set方法,然后会把当前对象myBoy的isa指针指向这个子类。注意虽然当前对象的isa指针变了,但是当前对象在内存中没有变,并没有生成子类的对象。

2.当myBoy的name属性发生变化的时候,会调用子类对象的set方法,在这个方法中,会先调用willChangeValueForKey:方法,然后调用父类(boy类)的set方法设置属性值,最后调用didChangeValueForKey:方法,这个时候就会调用观察者的observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context方法,告诉观察者观察的属性改变了。

3.手动调用系统kvo,首先要完成前面1、2代码,然后在boy类种重写方法:

//设置手动或者自动开启KVO 默认为YES 如果设置为NO 需要手动调用
+(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
{
    return YES;
}

然后在需要触发通知的地方调用以下方法,也就是说即使不改变myBoy种name的值,只要调用以下两个方法也可以实现KVO通知:

[self.myBoy willChangeValueForKey:@"name"];
[self.myBoy didChangeValueForKey:@"name"];

2.实现简易kvo,我们在上面的需求上实现一个简易kvo

A. 实现逻辑为下面三个步骤:

a>创建子类
b>为子类添加该属性的set方法
c>将myBoy的isa指针指向子类

B. 具体实现代码

@implementation NSObject (kvo)
-(void)JK_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
{
    // a创建子类 需要在子类的set方法中实现通知观察者observer
    NSString*subname = [NSString stringWithFormat:@"JK_%@",NSStringFromClass([self class])] ;
    Class newclass = NSClassFromString(subname);
    if (!newclass)
     {
        newclass = objc_allocateClassPair([self class], subname.UTF8String, 0);
     }
    objc_registerClassPair(newclass);
    
    // b为子类添加该属性的set方法 注意oc的方法实际上会变成调用函数 该函数的前两个参数必须是id self, SEL _cmd
    // 最后一个参数表示该函数的参数 v表示void @表示对象 :表示SEL
    class_addMethod(newclass, @selector(setName:), (IMP)setName, @"v@:@".UTF8String);
    
    // cisa指针指向新子类
    object_setClass(self, newclass);
    // 把观察者关联到自己身上 用assign的方式 避免循环引用
    objc_setAssociatedObject(self, @"observer", observer, OBJC_ASSOCIATION_ASSIGN);
}
// 实现子类的set方法
void setName(id self, SEL _cmd, NSString* name)
{
    
    Class subclass = [self class];
    Class superclass = class_getSuperclass(subclass);
    object_setClass(self, superclass);
    // 调用本身的set方法设置值
    objc_msgSend(self, _cmd, name);
    object_setClass(self, subclass);
    //通知观察者
    id observer = objc_getAssociatedObject(self, @"observer");
    if (observer) { //当观察者被销毁后不会崩溃
        [observer observeValueForKeyPath:NSStringFromSelector(_cmd) ofObject:self change:@{@"new":name} context:nil];
    }
}

调用以下方法添加观察者,就可以如同系统kvo方法一样观察到属性的变化了:

-(void)JK_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context

备注

kvo官方地址:
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html
本文demon地址:
https://github.com/songjk/ioskvo.git

相关文章

  • iOS - KVO

    [toc] 参考 KVO KVC 【 iOS--KVO的实现原理与具体应用 】 【 IOS-详解KVO底层实现 】...

  • ios KVO原理和实现简易KVO

    一内容概述 本文主要分析kvo的底层原理,以及如何自己实现简易kvo。kvo的官方解释:Key-value obs...

  • IOS底层(三) KVO底层实现原理

    @[TOC](IOS底层(三) KVO底层实现原理 ) 一,KVO简述 KVO的全称 Key-Value Obse...

  • iOS 自定义KVO

    自己实现kvo之前,需要知道iOS系统对kvo的实现。 系统实现kvo的原理 这依赖了OC强大的runtime特性...

  • iOS-底层原理-自定义KVO

    1.自定义KVO 1.上一篇博客了解了iOS 系统KVO的底层实现原理,那么这里进行自定义KVO,更好的理解原理和...

  • iOS KVO

    KVO 示例 KVO的实现原理

  • iOS-KVO(二) 使用注意点

    iOS-KVO(一) 基本操作iOS-KVO(二) 使用注意点iOS-KVO(三) 窥探底层实现iOS-KVO(四...

  • iOS-KVO(三) 窥探底层实现

    iOS-KVO(一) 基本操作iOS-KVO(二) 使用注意点iOS-KVO(三) 窥探底层实现iOS-KVO(四...

  • iOS-KVO(四) 自定义KVO+Block

    iOS-KVO(一) 基本操作iOS-KVO(二) 使用注意点iOS-KVO(三) 窥探底层实现iOS-KVO(四...

  • iOS-KVO(一) 基本操作

    iOS-KVO(一) 基本操作iOS-KVO(二) 使用注意点iOS-KVO(三) 窥探底层实现iOS-KVO(四...

网友评论

      本文标题:ios KVO原理和实现简易KVO

      本文链接:https://www.haomeiwen.com/subject/plvpuqtx.html