準(zhǔn)備工作
- 重寫一個分類 一般是NSObject
- 需要導(dǎo)入一個頭文件
#import <objc/message.h>
頭文件聲明方法
- (void)rylsj_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
方法實現(xiàn)
//self -->被觀察者person
//observer -->觀察者
- (void)rylsj_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context{
/*
1泰佳、自定義一個子類
2掺炭、重寫setName方法份蝴,在方法中铃彰,調(diào)用super的通知觀察者
3、修改當(dāng)前的isa指針昧港,指向自定義的子類
*/
//1.動態(tài)生成一個類
//1.1獲取類名
NSString *oldClassName = NSStringFromClass([self class]);
NSString *newClassName = [@"RYLSJKVO_" stringByAppendingString:oldClassName];
const char *newName = [newClassName UTF8String];
//創(chuàng)建一個類的class
Class myClass = objc_allocateClassPair([self class], newName, 0);
//注冊類
objc_registerClassPair(myClass);
//2.添加set方法
class_addMethod(myClass, @selector(setName:), (IMP)setName, "v@:@");
//3.修改isa指針
object_setClass(self, myClass);
//4.保存觀察者對象
objc_setAssociatedObject(self, @"objc", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
說明
- objc_registerClassPair 這個方法是重新注冊了一個新類
- 參數(shù)使用的是char * 的 const char *newName = [newClassName UTF8String]; 這樣可以把OC的字符串轉(zhuǎn)換為char * 類型的
方法實現(xiàn)
void setName(id self,SEL _cmd,NSString *newName){
//NSLog(@"調(diào)用了setName方法召调!");
//保存子類型
id class = [self class];
//改變self的isa指針
object_setClass(self, class_getSuperclass(class));
//調(diào)用父類的set方法
objc_msgSend(self, @selector(setName:),newName);
//NSLog(@"修改完畢!");
//拿到觀察者
id objc = objc_getAssociatedObject(self, @"objc");
//通知觀察者
objc_msgSend(objc, @selector(observeValueForKeyPath:ofObject:change:context:),self,@"name",nil,nil);
//改回子類類型
object_setClass(self, class);
}
說明
- 這里是C語言方法
- 這里修改了指針為自定義的對象
- 需要在setting中 搜索msg把YES設(shè)置為NO