iOS中KVC與KVO的應用解析

iOS中KVC與KVO的應用解析

1、NSKeyValueCoding(KVC)

一、從一個小例子引入

KVC鍵值編碼是Object-C爲咱們提供的一種對成員變量賦值的方法。在探討其方法以前,咱們先來看一個小例子:數組

首先,建立一個數據模型model類:數據結構

//.h文件
#import <Foundation/Foundation.h>
@interface Model : NSObject
{
    @public//將成員變量設置爲公有的 以便其餘文件有訪問權限
    NSString * str;
}
@end

咱們在其餘文件中有兩種方法str進行賦值和取值:函數

    Model * model = [[Model alloc]init];
    model->str=@"312";//普通方法賦值
    [model setValue:@"321" forKey:@"str"];//kvc賦值
    NSLog(@"%@",model->str);//普通方法取值
    NSLog(@"%@",[model valueForKey:@"str"]);//kvc取值

一樣的,對於用@property聲明的變量,使用kvc的效果和使用點語法,setter,getter方法的效果是同樣的。學習

二、KVC有關函數方法詳解

經過上面的例子,咱們已經能夠簡單瞭解KVC是幹什麼的了,下面是一些經常使用方法。編碼

+ (BOOL)accessInstanceVariablesDirectly;spa

這個方法相似一個開關,默認返回爲YES,表示支持KVC方式賦值,也能夠在子類中將其重寫,若是返回爲NO,則再進行KVC會拋出異常。code

- (id)valueForKey:(NSString *)key;server

經過鍵取值對象

- (void)setValue:(id)value forKey:(NSString *)key;rem

經過字符串鍵給成員變量賦值

- (BOOL)validateValue:(inout id *)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;

系統默認實現的方法,驗證一個鍵值是否有效

- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;

將取到的值放入一個可變數組中

- (NSMutableOrderedSet *)mutableOrderedSetValueForKey:(NSString *)key NS_AVAILABLE(10_7, 5_0);

將取到的值放入可變的有序集合中

- (NSMutableSet *)mutableSetValueForKey:(NSString *)key;

將取到的值放入可變的集合中

- (id)valueForKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;

上面這兩個方法分別是經過路徑賦值與取值,數據結構相似地圖,好比在model類中有一個成員變量model2,在Model2類中有一個字符串,咱們能夠經過以下的方式賦值取值

//Model.h
#import "Model2.h"
@interface Model : NSObject
{
    @public
    NSString * str;
    Model2 * model2;
}
//Model2.h
@interface Model2 : NSObject
{
@public
    NSString * str2;
}
@end
//其餘文件
    Model * model = [[Model alloc]init];
    Model2 * model2 = [[Model2 alloc]init];
    model->model2=model2;
    [model setValue:@"123" forKeyPath:@"model2.str2"];
    NSLog(@"%@",[model valueForKeyPath:@"model2.str2"]);

 

- (NSMutableArray *)mutableArrayValueForKeyPath:(NSString *)keyPath;
- (NSMutableOrderedSet *)mutableOrderedSetValueForKeyPath:(NSString *)keyPath NS_AVAILABLE(10_7, 5_0);
- (NSMutableSet *)mutableSetValueForKeyPath:(NSString *)keyPath;

上面三個方法與前面相似,只是是從路徑取值的。

- (id)valueForUndefinedKey:(NSString *)key;

這個方法能夠獲取沒有提早定義的成員變量的值,好比運行時建立的,下面這個方法是給未定義的成員變量賦值

- (void)setValue:(id)value forUndefinedKey:(NSString *)key;

注意:這兩個方法默認的實現會拋出異常,子類必須重寫才能使用。

- (void)setNilValueForKey:(NSString *)key;

將成員變量置爲nil

- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;

根據鍵值獲取鍵值對字典

- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;

經過字典對成員變量贊成賦值,常常使用

2、NSKeyValueObservingCustomization(KVO)

KVO是一種消息監聽機制,能夠在某個量發生變化的時候將消息傳送給監聽者,所以普遍用於傳值,界面低耦合等邏輯中。KVO機制的核心是如下三個方法:

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

使用這個方法註冊一個監聽者,參數解釋以下:

observer:監聽者對象

keyPath:監聽的參數

options:監聽選項

context:參數傳遞

監聽的選項枚舉以下:

typedef NS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) {
    NSKeyValueObservingOptionNew = 0x01,//回調的字典中存放新值
    NSKeyValueObservingOptionOld = 0x02,//回調的字典中存放舊值
    NSKeyValueObservingOptionInitial ,//值改變前進行回調
    NSKeyValueObservingOptionPrior//改變先後都進行回調

};
//回調字典後面會解釋

 

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

這兩個方法都是用來移除監聽者

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;

這個方法是監聽對象數據改變時回調的方法,change是一個字典,字典中根據監聽的選項不一樣,存放不一樣的值(新或者舊)。context是傳遞的參數。

代碼示例:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
     model = [[Model alloc]init];
    //添加監聽者
    [model addObserver:self forKeyPath:@"str" options:NSKeyValueObservingOptionNew context:@"321"];
    [model setValue:@"qw" forKey:@"str"];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    if ([keyPath isEqualToString:@"str"]) {
        NSLog(@"%@",context);
    }
}

學習使用 歡迎轉載

 

專一技術,熱愛生活,交流技術,也作朋友。

——琿少 QQ羣:203317592

相關文章
相關標籤/搜索