Runtime | 自定義KVO

準(zhǔn)備工作

  1. 重寫一個(gè)分類 一般是NSObject
  2. 需要導(dǎo)入一個(gè)頭文件
#import <objc/message.h>

頭文件聲明方法

- (void)rylsj_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;

方法實(shí)現(xiàn)

//self -->被觀察者person
//observer -->觀察者
- (void)rylsj_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context{
    /*
     1、自定義一個(gè)子類
     2、重寫setName方法,在方法中,調(diào)用super的通知觀察者
     3、修改當(dāng)前的isa指針,指向自定義的子類
     */
     
    //1.動(dòng)態(tài)生成一個(gè)類
    //1.1獲取類名
    NSString *oldClassName = NSStringFromClass([self class]);
    NSString *newClassName = [@"RYLSJKVO_" stringByAppendingString:oldClassName];
    const char *newName = [newClassName UTF8String];
    
    //創(chuàng)建一個(gè)類的class
    Class myClass = objc_allocateClassPair([self class], newName, 0);
    //注冊(cè)類
    objc_registerClassPair(myClass);
    //2.添加set方法
    class_addMethod(myClass, @selector(setName:), (IMP)setName, "v@:@");
    //3.修改isa指針
    object_setClass(self, myClass);
    //4.保存觀察者對(duì)象
    objc_setAssociatedObject(self, @"objc", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

說(shuō)明

  1. objc_registerClassPair 這個(gè)方法是重新注冊(cè)了一個(gè)新類
  2. 參數(shù)使用的是char * 的 const char *newName = [newClassName UTF8String]; 這樣可以把OC的字符串轉(zhuǎn)換為char * 類型的

方法實(shí)現(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); 
}

說(shuō)明

  1. 這里是C語(yǔ)言方法
  2. 這里修改了指針為自定義的對(duì)象
  3. 需要在setting中 搜索msg把YES設(shè)置為NO
設(shè)置msg為NO
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容