[求助]新人关于KVO问题请教,谢谢大家
程序员文章站
2022-04-13 15:33:30
...
最近研究runtime,在网上看到一个大神写的runtime手动实现KVO,自己试了试
但是却出现一些问题,想求助各位大神 新人第一次发帖。
结构:
- 在ViewController中监听people(继承自NSobject)类的name。
- 监听类NSObject (KVO),具体的监听实现。
方法:
* people类:
#import <Foundation/Foundation.h>
@interface people : NSObject
@property(nonatomic,copy)NSString *name;
@end
- NSObject (KVO)
#import <Foundation/Foundation.h>
@interface NSObject (KVO)
-(void)PE_addobserve:(NSObject *)observer forkeyPath:(NSString *)keypath options:(NSKeyValueObservingOptions)options context:(void *)context;
@end
具体实现
#import "NSObject+KVO.h"
#import <objc/runtime.h>
#import <objc/message.h>
@implementation NSObject (KVO)
-(void)PE_addobserve:(NSObject *)observer forkeyPath:(NSString *)keypath options:(NSKeyValueObservingOptions)options context:(void *)context
{
//保存observer
objc_setAssociatedObject(self, (__bridge const void*)@"objc", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
//动态生成新的对象
NSString *oldstring=NSStringFromClass([self class]);
NSString *newString=[@"PE_" stringByAppendingString:oldstring];
const char* newname=[newString UTF8String];
//注册新类,添加方法
Class newclass=objc_allocateClassPair([self class], newname, 0);
class_addMethod(newclass, @selector(setName:),(IMP)setName,"aaa@qq.com:@");
objc_registerClassPair(newclass);
object_setClass(self, newclass);
}
//set 方法的重写
void setName(id self,SEL _cmd,NSString* name)
{
//保存自己类
Class myclass=[self class];
//self指向父类
object_setClass(self,class_getSuperclass([self class]));
// struct objc_super sup;
//
// sup.receiver=myclass;
//
// sup.super_class=class_getSuperclass([self class]);
//父类执行方法
objc_msgSend(self,@selector(setName:),name);
//获取observer对象
id objc= objc_getAssociatedObject(self, (__bridge const void*)@"objc");
//通知observer执行方法
objc_msgSend(objc, @selector(addObserver:forKeyPath:options:context:),self,name,NSKeyValueObservingOptionNew,nil);
//self指回来
object_setClass(self, myclass);
}
*VC中的处理
- (void)viewDidLoad {
[super viewDidLoad];
self.pe=[[people alloc]init];
// self.pe.name=[[NSString alloc]init];
[self.pe setValue:@"黄龙" forKeyPath:@"name"];
[self.pe PE_addobserve:self forkeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
UIButton *btn =[UIButton buttonWithType:UIButtonTypeCustom];
btn.frame=CGRectMake(100,100, 200, 100);
btn.backgroundColor=[UIColor brownColor];
[btn addTarget:self action:@selector(btnclick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
// [self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)btnclick
{
self.pe.nameaaa@qq.com"小黄狗";
// [self.pe setValue:@"小黄狗" forKeyPath:@"name"];
}
-(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context
{
NSLog(@"我可能要换个名字了:%@",[self.pe valueForKeyPath:@"name"]);
}
但是当我点击按钮的的时候却爆出内存错误:
我尝试将people中的name的属性改为strong,只是一种尝试
@property(nonatomic,strong)NSString *name;
依然出现内存错误:
第二张图片截图的时候不小心在方法中加了4,报错未实现警告,但是不影响
尝试初始化依然不行
小白有点麻爪求助
附上源码地址 :源码
上一篇: iOS KVO的使用和原理实现