KVO

原理

當(dāng)你觀察一個對象時,一個新的類會動態(tài)被創(chuàng)建。這個類繼承自該對象的原本的類,并重寫了被觀察屬性的 setter 方法。自然,重寫的 setter 方法會負(fù)責(zé)在調(diào)用原 setter方法之前和之后,通過調(diào)willChangeValueForKey: 和 didChangevlueForKey:這兩個方法來通知所有觀察對象值的更改。最后把這個對象的 isa 指針 指向這個新創(chuàng)建的子類,對象就神奇的變成了新創(chuàng)建的子類的實例。不僅如此,Apple 還重寫了 -class 方法,企圖欺騙我們這個類沒有變,就是原本那個類。

原理

1.使用姿勢 http://zhangbuhuai.com/understanding-kvo/

  • 監(jiān)聽的時候傳入上下文來區(qū)分
  • 移除的時候根據(jù)上下文來移除
  • 為了避免取消訂閱時造成的crash,可以把取消訂閱代碼放在@try-@catch語句中
static void * zwContentSize = &zwContentSize;
    
- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    // 1. subscribe
    [_tableView addObserver:self
                 forKeyPath:NSStringFromSelector(@selector(contentSize))
                    options:NSKeyValueObservingOptionNew
                    context:zwContentSize];
}
    
// 2. responding
- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    if (context == zwContentSize) {
        // configure view
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}
    
- (void)dealloc {
    @try {
        // 3. unsubscribe
        [_tableView removeObserver:self
                        forKeyPath:NSStringFromSelector(@selector(contentSize))
                           context:zwContentSize];
    }
    @catch (NSException *exception) {
        
    }
}

2.如何自己實現(xiàn)KVO http://tech.glowing.com/cn/implement-kvo/

3.手動設(shè)定KVO https://yq.aliyun.com/articles/30483

如果將一個對象設(shè)定成屬性,這個屬性是自動支持KVO的,如果這個對象是一個實例變量,那么,這個KVO是需要我們自己來實現(xiàn)的

//
//  Student.m
//  SuperNotification
//
//  Copyright (c) 2014年 Y.X. All rights reserved.
//

#import "Student.h"

@implementation Student

@synthesize name = _name;
- (void)setName:(NSString *)name
{
    _name = name;
}
- (NSString *)name
{
    return _name;
}


// 手動設(shè)定KVO
- (void)setAge:(NSString *)age
{
    [self willChangeValueForKey:@"age"];
    _age = age;
    [self didChangeValueForKey:@"age"];
}
- (NSString *)age
{
    return _age;
}

// 該方法來告訴系統(tǒng)是否監(jiān)聽某個key
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
{
    // 如果監(jiān)測到鍵值為age,則指定為非自動監(jiān)聽對象
    if ([key isEqualToString:@"age"])
    {
        return NO;
    }
    
    return [super automaticallyNotifiesObserversForKey:key];
}

@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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