IOS SDK詳解之KVO

來源:互聯網
上載者:User

IOS SDK詳解之KVO

 

 前言:KVC和KVO是協助我們駕馭objective C動態特性工具。KVO是建立在KVC基礎上的,所以不瞭解KVC的同學可以參見我的這篇部落格。這裡我不會再重複講解KVC。
 
本文的內容

KVO的定義
KVO的典型使用情境。
手動KVO
幾點KVO要說的地方

一 KVO的定義

KVO提供了一種key-value-observing的機制,也就是說可以通過監聽key,來獲得value的變化。用來在對象之間監聽狀態變化。使用KVO的類要遵循 協議,事實上,任何繼承自NSObject的類,都遵循了這個協議。而Object C中,幾乎所有的類都源自NSObject

使用KVO通常分為三步

1.1 訂閱想要監聽的keypath

用函數

- (void)addObserver:(NSObject *)anObserver         forKeyPath:(NSString *)keyPath            options:(NSKeyValueObservingOptions)options            context:(void *)context

註冊通知

observer:觀察者,也就是KVO通知的訂閱者。訂閱著必須實現
observeValueForKeyPath:ofObject:change:context:方法 keyPath:描述將要觀察的屬性,相對於被觀察者。 options:KVO的一些屬性配置;有四個選項。 context: 上下文,這個會傳遞到訂閱著的函數中,用來區分訊息,所以應當是不同的。

options所包括的內容

NSKeyValueObservingOptionNew:change字典包括改變後的值 NSKeyValueObservingOptionOld:change字典包括改變前的值 NSKeyValueObservingOptionInitial:註冊後立刻觸發KVO通知 NSKeyValueObservingOptionPrior:值改變前是否也要通知(這個key決定了是否在改變前改變後通知兩次)
1.2 響應狀態變化

每當監聽的keyPath發生變化了,就會在這個函數中回調。

- (void)observeValueForKeyPath:(NSString *)keyPath                      ofObject:(id)object                        change:(NSDictionary *)change                       context:(void *)context
keyPath:被監聽的keyPath , 用來區分不同的KVO監聽。 object: 被觀察修改後的對象(可以通過object獲得修改後的值) change:儲存資訊改變的字典(可能有舊的值,新的值等) context:上下文,用來區分不同的KVO監聽。
1.3 在適當的時候,取消訂閱

通常使用兩個函數

- (void)removeObserver:(NSObject *)anObserver            forKeyPath:(NSString *)keyPath- (void)removeObserver:(NSObject *)observer            forKeyPath:(NSString *)keyPath               context:(void *)context

一般在remove的時候會這麼寫,因為remove的時候,無法判讀啊remove是否成功了

    @try {        [object removeObserver:self forKeyPath:keyPath];    }    @catch (NSException *exception) {        NSLog(@%@,exception);    }
二 KVO的典型使用情境 - model 與 view的同步

這裡,你將看到一個完整的KVO的例子。和上篇KVC一樣,我寫了個類似的demo。點擊random會隨機改變User的age,然後UI上要進行同步顯示出新的和舊的age。

實現過程如下:
定義了一個User類來作為Model

@interface User : NSObject@property (strong,nonatomic) NSString * name;@property (nonatomic) NSUInteger age;@end

定義兩個靜態變數,一個作為keyPath,一個作為context

static  NSString * observename = @age;static void * privateContext = 0;

然後在viewWillAppear中註冊(訂閱)KVO,在viewWillDisappear中刪除KVO

-(void)viewWillAppear:(BOOL)animated{    [self.user addObserver:self                forKeyPath:observename                   options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:privateContext];}-(void)viewWillDisappear:(BOOL)animated{    @try {        [self.user removeObserver:self forKeyPath:observename];    }    @catch (NSException *exception) {        NSLog(@%@,exception);    }}

當點擊random的時候,age會改變

- (IBAction)random:(id)sender {    self.user.age = arc4random()%100 +1;}

然後,在上面提到的函數中進行model和view的同步

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{    if (context == privateContext) {        if ([keyPath isEqualToString:observename]) {            NSNumber * old = [change objectForKey:NSKeyValueChangeOldKey];            NSNumber * new = [change objectForKey:NSKeyValueChangeNewKey];            self.lastvalue.text = [NSString stringWithFormat:@%@,old];            self.newvalue.text = [NSString stringWithFormat:@%@,new];        }    }}
三 手動KVO

KVO的實現,是對註冊的keyPath中自動實現了兩個函數,在Setter中,自動調用。

- (void)willChangeValueForKey:(NSString *)key- (void)didChangeValueForKey:(NSString *)key

可能有時候,我們要實現手動的KVO
這時候需要關閉自動產生KVO通知,然後手動的調用,手動通知的好處就是,可以靈活加上自己想要的判斷條件。例如

+(BOOL)automaticallyNotifiesObserversOfAge{    return NO;}-(void)setAge:(NSUInteger)age{    if (age < 22) {        return;    }    [self willChangeValueForKey:@age];    _age = age;    [self didChangeValueForKey:@age];}
四 KVO要提到的幾點KVO和Context

由於Context通常用來區分不同的KVO,所以context的唯一性很重要。通常,我的使用方式是通過在當前.m檔案裡用靜態變數定義。

static void * privateContext = 0;
KVO與線程

KVO的響應和KVO觀察的值變化是在一個線程上的,所以,大多數時候,不要把KVO與多線程混合起來。除非能夠保證所有的觀察者都能安全執行緒的處理KVO

監聽變化的值

改變前和改變後分別為

id oldValue = change[NSKeyValueChangeOldKey];id newValue = change[NSKeyValueChangeNewKey];

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.