首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C >> 關於C

Objective-C KVO (Key-Value Observing) 完整教學:自動/手動通知與實戰範例

     編輯:關於C

KVO 核心條件

  1. 被觀察物件需對屬性提供符合 KVC 的存取器(setX:/x)。
  2. 觀察者實作 observeValueForKeyPath:ofObject:change:context: 接收回呼。
  3. 觀察者呼叫 addObserver:forKeyPath:options:context: 註冊。

必須在 dealloc 中呼叫 removeObserver:forKeyPath:,否則物件釋放後收到通知會崩潰。

選項 options 詳解

常數含義
NSKeyValueObservingOptionNewchange 字典包含 NSKeyValueChangeNewKey(新值)
NSKeyValueObservingOptionOld包含 NSKeyValueChangeOldKey(舊值)
NSKeyValueObservingOptionInitial註冊瞬間立即發送一次通知(舊值為 nil)
NSKeyValueObservingOptionPrior變更前/後各發一次(NSKeyValueChangeNotificationIsPriorKey)

Change 字典鍵值

  • NSKeyValueChangeKindKey:變更類型(Setting/Insertion/Removal/Replacement)
  • NSKeyValueChangeNewKey、OldKey、IndexesKey、IsPriorKey

範例:老爸監控兒子女友


@interface Son : NSObject
@property (nonatomic, copy) NSString *girl_friend_name;
- (void)fall_in_love_with:(NSString*)name;
- (void)think;
@end

@implementation Son
- (void)fall_in_love_with:(NSString*)name { self.girl_friend_name = name; }
- (void)think { NSLog(@"My love girl is %@ ... Does baba know?", girl_friend_name); }
@end

@interface Baba : NSObject
@property (strong) Son *son;
@end

@implementation Baba
- (instancetype)initWithSon:(Son*)s {
    if (self = [super init]) {
        _son = s;
        [s addObserver:self
           forKeyPath:@"girl_friend_name"
              options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld | NSKeyValueObservingOptionInitial
              context:nil];
    }
    return self;
}
- (void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)obj change:(NSDictionary*)change context:(void*)ctx {
    NSString *old = change[NSKeyValueChangeOldKey];
    NSString *new = change[NSKeyValueChangeNewKey];
    if (!old) { NSLog(@"First time induction!"); return; }
    if ([new isEqualToString:@"libinbin"]) [obj fall_in_love_with:@"fanbinbin"]; // 強行改變
    NSLog(@"Son's %@ changed from %@ to %@", keyPath, old, new);
}
- (void)dealloc { [self.son removeObserver:self forKeyPath:@"girl_friend_name"]; }
@end

進階:手動控制通知(繞過自動 KVO)

重寫類別方法 +automaticallyNotifiesObserversForKey: 返回 NO 關閉自動通知,再在 setter 中手動呼叫:


+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key {
    return ![key isEqualToString:@"girl_friend_name"];
}
- (void)setGirl_friend_name:(NSString*)name {
    [self willChangeValueForKey:@"girl_friend_name"];
    _girl_friend_name = @"女學霸"; // 假裝給老爸看
    [self didChangeValueForKey:@"girl_friend_name"];
    _girl_friend_name = name;      // 真實值
}

結果:老爸只看到「女學霸」,兒子實際女友不變,達到隱私保護與誤導並存。

記憶體管理提醒

  • ARC 環境下 dealloc 不能呼叫 [super dealloc]。
  • 觀察者移除順序:先 removeObserver,再釋放被觀察物件。
  • context 參數可用於區分多個觀察同一鍵路徑的觀察者,傳遞 self 或唯一指標。

總結

KVO 是 Cocoa 綁定機制的基石,掌握自動/手動通知切換、change 字典解析、生命週期管理 三大核心,即可靈活實現屬性監聽、資料同步、UI 自動更新等模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved