iOS 帶block的KVO

對(duì)于iOS 開發(fā)者來說,KVO(key-value-observing)的使用大家已經(jīng)不再陌生,而且使用起來也是非常方便。

KVO的簡單使用:

KVOObject *object = [[KVOObject alloc] init];
 [object addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil];
object.name = @"123";

這樣我們就已經(jīng)為object的name屬性添加了監(jiān)聽,只要object的name屬性發(fā)生改變,我們就可以通過KVO的回調(diào)方法獲取其新值。

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
     NSLog(@"新值為 %@", [change objectForKey:NSKeyValueChangeNewKey]);
}
2017-12-18 16:44:36.096356+0800 KVO[5973:274888] 新值為 123

KVO的基本使用就是這樣,那么KVO是用什么原理實(shí)現(xiàn)的呢?如何自己實(shí)現(xiàn)一個(gè)帶block的KVO呢?
KVO原理:例如在為Object類添加監(jiān)聽時(shí),蘋果動(dòng)態(tài)的為我們添加了一個(gè)類,類的名字是NSKVONotifying_Object,并且NSKVONotifying_Object是Object的子類,然后把指向Object的類指向了NSKVONotifying_Object,然后在子類中重寫setter方法。

直接上代碼:

-(void)sp_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context callBack:(void (^)(id _Nullable))block{
    NSString *className = [@"SP_" stringByAppendingString:NSStringFromClass([self class])];
    Class newClass = objc_allocateClassPair([self class], className.UTF8String, 0);//動(dòng)態(tài)生成一個(gè)類,類名在原類基礎(chǔ)上加一個(gè)前綴SP_
    objc_registerClassPair(newClass);//注冊(cè)該類
    object_setClass(self, newClass);//把指針指向子類
    class_addMethod(newClass, @selector(setName:), (IMP)classSetName, "v@:@");//重寫set方法
    objc_setAssociatedObject(self, &blockKey, block, OBJC_ASSOCIATION_RETAIN_NONATOMIC);//關(guān)聯(lián)block對(duì)象
    
}

void classSetName(id self,SEL _cmd, NSString * newName){
    struct objc_super superClass = {
        .receiver = self,
        .super_class = class_getSuperclass(object_getClass(self))
    };
    
    // 調(diào)用父類中setter方法
    objc_msgSendSuper(&superClass,_cmd,newName);
    void(^block)(id paramter) = objc_getAssociatedObject(self, &blockKey);
    if (block) {
        block(newName);
    }
}

viewController中調(diào)用:

@interface ViewController ()
@property (nonatomic, strong) KVOObject * object;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    KVOObject *object = [KVOObject new];
    [object sp_addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil callBack:^(id  _Nullable paramter) {
        NSLog(@"block回調(diào): %@\nobject name屬性值: %@",paramter,object.name);
    }];
    _object = object;
}


-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    static int a = 0;
    a++;
    _object.name = [NSString stringWithFormat:@"%d",a];
}
KVO[6404:296022] block回調(diào): 1
object name屬性值: 1
2017-12-18 17:05:34.432499+0800 KVO[6404:296022] block回調(diào): 2
object name屬性值: 2
?著作權(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),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,041評(píng)論 0 9
  • 上半年有段時(shí)間做了一個(gè)項(xiàng)目,項(xiàng)目中聊天界面用到了音頻播放,涉及到進(jìn)度條,當(dāng)時(shí)做android時(shí)候處理的不太好,由于...
    DaZenD閱讀 3,098評(píng)論 0 26
  • 本文分為2個(gè)部分:概念與應(yīng)用。概念部分旨在剖析 KVO 這一設(shè)計(jì)模式的實(shí)現(xiàn)原理;應(yīng)用部分通過創(chuàng)建的項(xiàng)目,以說明 K...
    啊左閱讀 58,229評(píng)論 107 436
  • iOS--KVO的實(shí)現(xiàn)原理與具體應(yīng)用 長時(shí)間不用容易忘,這篇文章挺好的.轉(zhuǎn)載自看本文分為2個(gè)部分:概念與應(yīng)用。概念...
    超_iOS閱讀 1,502評(píng)論 0 17
  • 一、概述 KVO,即:Key-Value Observing,它提供一種機(jī)制,當(dāng)指定的對(duì)象的屬性被修改后,則其觀察...
    DeerRun閱讀 10,199評(píng)論 11 33

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