Objective-C KVC和KVO的使用

jopen 8年前發布 | 6K 次閱讀 iOS開發 移動開發 Objective-C

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; }</pre>

下面為打印結果:

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;

}   </pre>

下面是打印結果:

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對象可以進行某些操作,比如更新視圖

使用過程:

  1. 注冊,指定觀察哪些對象的哪些屬性
  2. 實現回調方法
  3. 移除觀察

首先定義一個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</pre>

然后在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</pre>

運行結果如下:

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

</div>

來自: http://www.cnblogs.com/smithjackyson/p/5131692.html

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!