KVC的使用通常情況下,我們都是通過屬性或者定義存取方法來對實例變數進行存取,但是除此之外,我們也可以通過Key-Value-Coding(KVC)鍵值編碼來存取的實例變數的值。使用KVC過程:首先,我們定義一個Person類,代碼如下:/**Person.h*/#import @interface...
KVC的使用
通常情況下,我們都是通過屬性或者定義存取方法來對實例變數進行存取,但是除此之外,我們也可以通過Key-Value-Coding(KVC)鍵值編碼來存取的實例變數的值。
使用KVC過程:
首先,我們定義一個Person類,代碼如下:
/* *Person.h */
#import <Foundation/Foundation.h>
@interface Person : NSObject
{ NSString *_name; } @end /* *Person.m */
#import "Person.h"
@implementation Person @end
然後創建Person類的實例,並使用KVC對_name實例變數進行賦值和取值操作:
#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { @autoreleasepool { Person *person = [[Person alloc] init];
//將person的實例變數_name賦值為SmithJackyson [person setValue:@"SmithJackyson" forKey:@"_name"];
//取出person的實例變數_name的值 NSString *name = [person valueForKey:@"_name"]; NSLog(@"name = %@",name); } return 0; }
下麵為列印結果:
2016-01-14 20:42:14.098 test[1559:113739] name = SmithJackyson
Program ended with exit code: 0
如果A類的屬性是一個B類,那麼為B類的屬性存取值就需要鍵路徑訪問屬性
假設Student類有一個Course類的屬性_course,其中Course類有一個屬性表示課程名稱NSString *_courseName;
下麵通過鍵路徑訪問屬性:
#import <Foundation/Foundation.h> #import "Student.h" #import "Course.h" int main(int argc, const char * argv[]) { @autoreleasepool { //註意:使用KVC是為實例存取實例變數,所以要初始化,並且為student的_course實例變數賦值為course,否則無法正確賦值 Student *student = [[Student alloc] init]; Course *course = [[Course alloc] init]; [student setValue:course forKey:@"_course"]; //為student實例變數_course的屬性_courseName賦值 [student setValue:@"English" forKeyPath:@"_course._courseName"]; //取得student實例變數_course的屬性_courseName的值 NSString *courseName = [student valueForKeyPath:@"_course._courseName"]; NSLog(@"courseName = %@",courseName); } return 0; }
下麵是列印結果:
2016-01-14 21:15:59.094 test[1867:123245] courseName = English
Program ended with exit code: 0
如果屬性是基本數據類型,可以使用字元串值直接賦值給屬性,取值時用字元串變數接受
KVO的使用
KVO,即:key-value observing,提供一種機制,假設A對象觀察B對象的指定屬性C,當B對象的屬性C的值發生變化,KVO會通知相應的觀察者A,A對象可以進行某些操作,比如更新視圖
使用過程:
- 註冊,指定觀察哪些對象的哪些屬性
- 實現回調方法
- 移除觀察
首先定義一個Person類,代碼如下:
#import <Foundation/Foundation.h> @interface Person : NSObject @property (nonatomic,copy)NSString *name; - (instancetype)initWithName:(NSString *)name; @end #import "Person.h" @implementation Person - (instancetype)initWithName:(NSString *)name { self = [super init]; if (self) { _name = name; } return self; } @end
然後在ViewController中使用KVO,代碼如下:
#import "ViewController.h" #import "Person.h" @interface ViewController () { Person *person; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; person = [[Person alloc] initWithName:@"John"]; //為person對象的屬性name添加觀察者為ViewController [person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:nil]; //可以通過下麵兩種方式改變name的值,都會觸發回調方法 person.name = @"SmithJackyson"; [person setValue:@"SmithJackyson" forKey:@"name"]; } //實現KVO回調方法,只要person的屬性name發生變化,就會回調這個方法 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
//change字典里存的內容是根據你註冊時的選項option決定的,如果為NSKeyValueObservingOptionNew,則字典里存的是改變後的值,key為new,同樣NSKeyValueObservingOptionOld,則字典里存的是改變前的值,key為old,如果兩者都有,則字典存儲著兩個值 if ([keyPath isEqualToString:@"name"] && object == person) { NSLog(@"now name = %@",person.name); } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
運行結果如下:
2016-01-15 16:17:29.102 test[1752:94898] now name = SmithJackyson
2016-01-15 16:17:29.102 test[1752:94898] now name = SmithJackyson
最後還需要移除觀察者
- (void)dealloc { [person removeObserver:self forKeyPath:@"name"]; }
轉載請註明:作者SmithJackyson