博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
iOS开发runtime实现KVO
阅读量:6835 次
发布时间:2019-06-26

本文共 2395 字,大约阅读时间需要 7 分钟。

利用运行时自定义KVO

//根据keypath 获取set方法-(SEL)getNewSelector:(NSString *)selectorName{    NSString *firstChar = [selectorName substringToIndex:1];    NSString *upFirst = [firstChar uppercaseString];    NSString *otherChar = [selectorName substringFromIndex:1];    NSString *newSelectorName = [NSString stringWithFormat:@"set%@%@:",upFirst,otherChar];    return  NSSelectorFromString(newSelectorName);}//根据set方法 获取keypath-(NSString *)getKeypath:(SEL)selector{    NSString *selectorName = NSStringFromSelector(selector);    selectorName = [selectorName substringFromIndex:3];    NSString *firstChar = [selectorName substringToIndex:1];    NSString *lowFirst = [firstChar lowercaseString];    NSString *otherChar = [selectorName substringFromIndex:1];        NSString *newChar = [NSString stringWithFormat:@"%@%@",lowFirst,otherChar];    return  [newChar substringToIndex:newChar.length-1];}复制代码

开始监听

-(void)shine_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath{    // 1.动态生成一个派生类    static Class newClass;    static dispatch_once_t predicate;    dispatch_once(&predicate, ^{        NSString * oldClassName = NSStringFromClass([self class]);        NSString *newClassName = [NSString stringWithFormat:@"Shine_%@",oldClassName];        //创建派生类        newClass = objc_allocateClassPair([self class], [newClassName UTF8String], 0);        //注册派生类        objc_registerClassPair(newClass);        //修改被观察者的isa指针,指向自定义的类        object_setClass(self, newClass);        //动态绑定        objc_setAssociatedObject(self, &Shine_KVO, observer, OBJC_ASSOCIATION_ASSIGN);    });    //2.生成新的set方法    SEL selector = [self getNewSelector:keyPath];    //3.添加新的set方法    class_addMethod(newClass, selector, (IMP)setObj, "v@:@");    }复制代码

属性更改回调

void setObj(id sf,SEL cd,id value){    NSString *keypath = [sf getKeypath:cd];    id oldValue = [sf valueForKey:keypath];    NSMutableDictionary *change = @{}.mutableCopy;    if (oldValue != nil) {        change[@"old"] = oldValue;    }    if (value != nil) {        change[@"new"] = value;    }    //取出当前类    id class = [sf class];    //指向父类    object_setClass(sf, class_getSuperclass(class));    //向父类发送消息    objc_msgSend(sf, cd ,value);    //获取动态绑定对象    id observe = objc_getAssociatedObject(sf, &Shine_KVO);    //监听回调    objc_msgSend(observe, @selector(shine_observeValueForKeyPath:ofObject:change:),keypath,sf,change);    //修改指向    object_setClass(sf, class);}复制代码

转载地址:http://grqkl.baihongyu.com/

你可能感兴趣的文章
Java调用 shell脚本阻塞
查看>>
rabbitmy实战
查看>>
mysql-Mac终端下遇到的问题总结
查看>>
表空间迁移(二)
查看>>
准备mysql函数库和PHP文件
查看>>
初学者应该了解的编程陷阱:javascript篇
查看>>
【安全牛学习笔记】手动漏洞挖掘(三)
查看>>
硬链接和软链接使用,以及区别
查看>>
history的详解与使用
查看>>
随机数
查看>>
【入门须知】学DIV CSS技术如何入门?
查看>>
Bullmind在线读书笔记软件
查看>>
wince 6.0 串口 读取 readfile 超时问题
查看>>
代码片段
查看>>
单例模式
查看>>
awk用法(三)
查看>>
谷歌深度学习公开课任务 5: Word2Vec&CBOW
查看>>
让Python不在mac的dock上显示火箭图标
查看>>
Oracle 数据库EM访问多个Instance
查看>>
理解 Delphi 的类(十) - 深入方法[28] - 递归函数实例: 搜索当前目录下的所有嵌套目录...
查看>>