KVO本质手写笔记

在这里插入图片描述
MHFPerson.h


#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface MHFPerson : NSObject
{
    @public
    int _no;
}
@property (assign, nonatomic)int age;
@end

NS_ASSUME_NONNULL_END

MHFPerson.m

#import "MHFPerson.h"

@implementation MHFPerson
- (void)setAge:(int)age
{
    _age = age;
    NSLog(@"调用setAge:方法");
}

- (void)willChangeValueForKey:(NSString *)key
{
    [super willChangeValueForKey:key];
    NSLog(@"willChangValueForKey");
}

- (void)didChangeValueForKey:(NSString *)key
{
    NSLog(@"didChangeValueForKey  - begin");
    [super didChangeValueForKey:key];
    NSLog(@"didChangeValueForKey  - end");
}
@end

伪代码NSKVONotifying_MHFPerson.h

#import "MHFPerson.h"

NS_ASSUME_NONNULL_BEGIN

@interface NSKVONotifying_MHFPerson : MHFPerson

@end

NS_ASSUME_NONNULL_END

伪代码NSKVONotifying_MHFPerson.m

#import "NSKVONotifying_MHFPerson.h"

@implementation NSKVONotifying_MHFPerson

/*
- (void)setAge:(int)age
{
    _NSSetIntValueAndNotify();

}

// 伪代码
void _NSSetIntValueAndNotify()
{
    [self willChangeValueForKey:@"age"];
    [super setAge:age];// 调用原来的setter方法实现
    [self didChangeValueForKey:@"age"];
}

- (void)didChangeValueForKey:(NSString *)key
{
    // 通知监听器,某某属性值发生了改变
    [observe observeValueForKeyPath:key ofObject:self change:nil context:nil];
    
}
 */


// 屏蔽内部实现,隐藏NSKVONotifying_MHFPerson类的存在
-(Class)class
{
    
}

- (void)dealloc
{
    // 收尾工作
}

- (BOOL)_isKVOA
{
    return YES;
}
@end

ViewController.m

#import "ViewController.h"
#import "MHFPerson.h"
#import <objc/runtime.h>
@interface ViewController ()
@property (strong, nonatomic)MHFPerson *personFirst;
@property (strong, nonatomic)MHFPerson *personSecond;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.personFirst = [[MHFPerson alloc]init];
//    self.personFirst.age = 10;
    self.personFirst->_no = 0;

    
    self.personSecond = [[MHFPerson alloc]init];
    self.personSecond.age = 11;
    
    
    NSLog(@"personFirst添加KVO监听之前 - %@  %@ \n methodForSelector:%p - %p\n",object_getClass(self.personFirst),object_getClass(self.personSecond),[self.personFirst methodForSelector:@selector(setAge:)],[self.personSecond methodForSelector:@selector(setAge:)]);

    // 给personFirst对象添加KVO监听
    [self.personFirst addObserver:self forKeyPath:@"no" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
    
    NSLog(@"personFirst添加KVO监听之后 - %@  %@\n methodForSelector:%p - %p",object_getClass(self.personFirst),object_getClass(self.personSecond),[self.personFirst methodForSelector:@selector(setAge:)],[self.personSecond methodForSelector:@selector(setAge:)]);
    

//    NSLog(@"类对象 - %@ %@",object_getClass(self.personFirst),object_getClass(self.personSecond));
//    NSLog(@"元类对象 - %@ %@",object_getClass(object_getClass(self.personFirst)),object_getClass(object_getClass(self.personSecond)));
    /*
     2019-03-05 15:22:40.993133+0800 OCEssence[23720:297744] 类对象 - NSKVONotifying_MHFPerson MHFPerson
     2019-03-05 15:22:43.886798+0800 OCEssence[23720:297744] 元类对象 - NSKVONotifying_MHFPerson MHFPerson
     */
    
    NSLog(@"类对象 - %@ %@",object_getClass(self.personFirst),object_getClass(self.personSecond));
    NSLog(@"类对象 - %@ %@",[self.personFirst class],[self.personSecond class]);
    [self printMethodNamesOfClass:object_getClass(self.personFirst)];
    [self printMethodNamesOfClass:object_getClass(self.personSecond)];
}



- (void)printMethodNamesOfClass:(Class)cls
{
    NSMutableArray *methodNameArray = [NSMutableArray array];
    unsigned int count;
    // 获得方法数组
    Method *methodList =  class_copyMethodList(cls, &count);
    for (int i = 0; i < count; i++) {
        Method first = methodList[i];
        NSString *methodName = NSStringFromSelector(method_getName(first));
        [methodNameArray addObject:methodName];
  
    }
    free(methodList);
    NSLog(@"%@",methodNameArray);
    //MHFPerson类中的方法有四个 @"setAge:",@"class",@"dealloc",@"_isKVOA"
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//    [self.personFirst setAge:20];
//    [self.personSecond setAge:21];
    [self.personFirst willChangeValueForKey:@"no"];
    self.personFirst->_no = 10;
    [self.personFirst didChangeValueForKey:@"no"];
    
    
    /*
     (lldb) p self.personFirst.isa
     (Class) $1 = NSKVONotifying_MHFPerson
     (lldb) p self.personSecond.isa
     (Class) $2 = MHFPerson
     */
    // self.personFirst.isa = NSKVONotifying_MHFPerson
    // self.personSecond.isa = MHFPerson
    // 实例对象的isa指向的是class类对象,说明personFirst这个类对象指向的是NSKVONotifying_MHFPerson这个类,而personSecond的类对象指向的是MHFPerson这个类,说明如果一个对象添加了KVO说明它的类对象不是以前指向的类对象,这个是Runtime在程序运行过程中动态创建的一个新的类NSKVONotifying_MHFPerson,这个是MHFPerson的一个子类
    
    
    /*
     personFirst添加KVO监听之后 - NSKVONotifying_MHFPerson  MHFPerson
     methodForSelector:0x1023c0fc2 - 0x102065200
     (lldb) p (IMP)0x1023c0fc2
     (IMP) $0 = 0x00000001023c0fc2 (Foundation`_NSSetIntValueAndNotify)
     (lldb) p (IMP)0x102065200
     (IMP) $1 = 0x0000000102065200 (OCEssence`-[MHFPerson setAge:] at MHFPerson.m:12)
     
     */
    
    
    
}

- (void)dealloc
{
    [self.personFirst removeObserver:self forKeyPath:@"age"];
}

//
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"监听到%@的%@属性值改变了 %@",object,keyPath,change);
}
@end
发布了337 篇原创文章 · 获赞 25 · 访问量 15万+

猜你喜欢

转载自blog.csdn.net/u012581760/article/details/88227585