詳解蘋果的黑魔法 – KVO 的奧秘

在iOS開發(fā)中,蘋果提供了許多機(jī)制給我們進(jìn)行回調(diào)。KVO(key-value-observing)是一種十分有趣的回調(diào)機(jī)制,在某個(gè)對象注冊監(jiān)聽者后,在被監(jiān)聽的對象發(fā)生改變時(shí),對象會發(fā)送一個(gè)通知給監(jiān)聽者,以便監(jiān)聽者執(zhí)行回調(diào)操作。最常見的KVO運(yùn)用是監(jiān)聽scrollView的contentOffset屬性,來完成用戶滾動(dòng)時(shí)動(dòng)態(tài)改變某些控件的屬性實(shí)現(xiàn)效果,包括漸變導(dǎo)航欄、下拉刷新控件等效果。
http://jbcdn2.b0.upaiyun.com/2015/12/36a1f0f0ac4af124dbdb65895b2d0fc9.gif

使用

KVO的使用非常簡單,使用KVO的要求是對象必須能支持kvc機(jī)制——所有NSObject的子類都支持這個(gè)機(jī)制。拿上面的漸變導(dǎo)航欄做,我們?yōu)閠ableView添加了一個(gè)監(jiān)聽者controller,在我們滑動(dòng)列表的時(shí)候,會計(jì)算當(dāng)前列表的滾動(dòng)偏移量,然后改變導(dǎo)航欄的背景色透明度。

<pre>//添加監(jiān)聽者
[self.tableView addObserver: self forKeyPath: @"contentOffset" options: NSKeyValueObservingOptionNew context: nil];
/**

  • 監(jiān)聽屬性值發(fā)生改變時(shí)回調(diào)
    */
  • (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
    CGFloat offset = self.tableView.contentOffset.y;
    CGFloat delta = offset / 64.f + 1.f;
    delta = MAX(0, delta);
    [self alphaNavController].barAlpha = MIN(1, delta);
    }
    </pre>

毫無疑問,kvo是一種非常便捷的回調(diào)方式,但是編譯器是怎么完成監(jiān)聽這個(gè)任務(wù)的呢?先來看看蘋果文檔對于KVO的實(shí)現(xiàn)描述

Automatic key-value observing is implemented using a technique called isa-swizzling… When an observer is registered for an attribute of an object the isa pointer of the observed object is modified, pointing to an intermediate class rather than at the true class ..
簡要的來說,在我們對某個(gè)對象完成監(jiān)聽的注冊后,編譯器會修改監(jiān)聽對象(上文中的tableView)的isa指針,讓這個(gè)指針指向一個(gè)新生成的中間類。從某個(gè)意義上來說,這是一場騙局。
<pre>typedef struct objc_class *Class;
typedef struct objc_object {
Class isa;
} *id</pre>

KVO使用三步走:

(1)注冊成為觀察者

(2)觀察者定義KVO的回調(diào)

(3)移除觀察者

來點(diǎn)實(shí)際的,還得上代碼:

KVOClass接口:
<pre>

import

@interface KVOClass : NSObject
@property(strong,nonatomic) NSString * name;
@end</pre>
KVOClass實(shí)現(xiàn)
<pre>#import "KVOClass.h"

@implementation KVOClass
//在init注冊觀察者
-(id) init
{
if (self = [super init]) {
[self addObserver:self
forKeyPath:@"name"
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
context:@"name"];
}
return self;
}

//重寫觀察方

  • (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
    if (context == @"name") {
    NSLog(@"name被改變啦!");
    } else {
    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
    }
    //移除觀察者
    -(void) dealloc
    {
    [self removeObserver:self forKeyPath:@"name"];
    [super dealloc];
    }
    @end</pre>
    待續(xù)。。。。。。。。。。。。。。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

  • 在iOS開發(fā)中,蘋果提供了許多機(jī)制給我們進(jìn)行回調(diào)。KVO(key-value-observing)是一種十分有趣的...
    流沙3333閱讀 428評論 0 0
  • 原文鏈接 基于觀察者設(shè)計(jì)模式,蘋果實(shí)現(xiàn)了notification和kvo兩套監(jiān)聽機(jī)制,兩者都實(shí)現(xiàn)了一對多的監(jiān)聽支持...
    sindri的小巢閱讀 48,481評論 48 222
  • 序言在iOS開發(fā)中,蘋果提供了許多機(jī)制給我們進(jìn)行回調(diào)。KVO(key-value-observing)是一種十分有...
    陌尚煙雨遙閱讀 560評論 0 0
  • FBKVOController是一個(gè)簡單易用的鍵值觀察框架,KVOController 對于 Cocoa 中 KV...
    我有小尾巴快看閱讀 1,436評論 0 0
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,101評論 0 9

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