iOS底層原理總結篇-- 深刻理解 KVC\KVO 實現機制(獲取類對象中的方法列表篇)

iOS底層原理總結--OC對象的本質(一) - 掘金數組

iOS底層原理總結--OC對象的本質(二) - 掘金app

iOS底層原理總結--OC對象的分類:instance、class、meta-calss對象的isa和superclass - 掘金post

iOS底層原理總結-- KVO/KVC的本質 - 掘金ui

...atom

一. 前言

本文是根據 iOS底層原理總結-- KVO/KVC的本質 - 掘金 延展的一篇文章,因此獲取的方法列表爲添加kvo監聽後,子類內部方法列表爲例子。spa

請先瀏覽 iOS底層原理總結-- KVO/KVC的本質 - 掘金 文章後閱讀本文。指針

代碼會在 ( iOS底層原理總結-- KVO/KVC的本質 - KVO的代碼實現 ) 此段代碼的基礎上進行更改,code

KVO的實現代碼

iOS底層原理總結-- KVO/KVC的本質 - KVO的代碼實現orm

獲取對象方法列表代碼實現

#import "ViewController.h"
#import "DLPerson.h"
#import <objc/runtime.h>
@interface ViewController ()
@property (nonatomic, strong) DLPerson *person1;
@property (nonatomic, strong) DLPerson *person2;
@end

@implementation ViewController

/** * 獲取對象方法列表 */
- (void)printMethodNamesOfClass:(Class)cls{
    unsigned int count;
    /// 獲取方法數組
    Method *methodList = class_copyMethodList(cls, &count);
    
    /// 存儲方法名
    NSMutableString *methodNames = [NSMutableString string];
    
    /// 遍歷全部的方法
    for (int i = 0; i < count; i++) {
        /// 獲取方法
        Method method = methodList[i];   /// 指針當作數組用。
        NSString *methodName = NSStringFromSelector( method_getName(method));
        [methodNames appendFormat:@"%@, ", methodName];
    }
    
    /// 釋放 C語言須要釋放
    free(methodList);
    
    /// 打印方法名
    NSLog(@"%@ %@", cls, methodNames);
}

- (void)viewDidLoad {
    [super viewDidLoad];
    self.person1 = [[DLPerson alloc]init];
    self.person1.age = 10;
    self.person2 = [[DLPerson alloc]init];
    self.person2.age = 1;
    
    ///> person1添加kvo監聽
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
    [self.person2 addObserver:self forKeyPath:@"age" options:options context:nil];
    
    
    [self printMethodNamesOfClass: object_getClass(self.person1)];
    [self printMethodNamesOfClass: object_getClass(self.person2)];
    
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    
    [self.person1 setAge:20];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    NSLog(@"監聽到了%@的%@屬性發生了改變%@",object,keyPath,change);
}

- (void)dealloc{
    ///> 使用結束後記得移除
    [self.person1 removeObserver:self forKeyPath:@"age"];
}
@end

複製代碼

打印結果cdn

DLPerson  setAge:, age,
    
    NSKVONotifying_DLPerson  setAge:, class, dealloc, _isKVOA,
    
複製代碼

打印結果分析

由打印結果可得出 當一個對象添加了KVO的監聽時,當前對象的isa指針指向的就不是你原來的類,指向的是另一個類對象,以下圖

第一行打印 爲person1的方法列表,未添加KVO監聽, isa直接指向的是DLPerson只有age的set和get方法

第二行打印 爲person2的方法列表,person添加KVO監聽後 isa指針指向的是NSKVONotifying_DLPerson CLass對象 方法列表包含了 delloc _isKVOA 和 setAge

... 持續更新

相關文章
相關標籤/搜索