iOS開發-KVC和KVO的理解


KVC和KVO看起來很專業,其實用起來還是比較簡單的,KVC(Key-value coding)可以理解為鍵值對編碼,如果對象的基本類型,那么鍵值對編碼實際上和get,set方法沒有區別,如果是屬性是另外一個對象,那么發現KVC用起來還是非常順手,KVO(key-value observing)是鍵值對的觀察者模式,如果對象的屬性發生變更,那么會觸發observeValueForKeyPath事件,KVO的這種通知特性讓我們在開發的時候節省了不必要的代碼,提高了開發效率。

KVC鍵值對編碼

KVC的操作方法由NSKeyValueCoding協議提供,NSObject就實現了這個協議,也就是說如果對象是NSObject的子對象那么就支持KVC操作,KVC有兩種操作方法,一種是設值,一種是取值,可以理解為getter和setter,不過稍微有所不同的是,設置對象值的方法中有兩個,setValue:屬性值 forKey:屬性名(一般的設置,比如說是說設置NSString,NSNumber等基本類類型,setetValue:屬性值 forKeyPath:屬性路徑(定義兩個對象,Person和Book,Person有一個類型為Book的屬性,如果需要在Person中設置Book的值,那么可以使用此方法),讀取的也有兩種valueForKey:屬性名、valueForKeyPath:屬性名。

Person.h中的代碼:

//
//  Person.h
//  BugDemo
//http://www.cnblogs.com/xiaofeixiang/
//  Created by keso on 15/2/8.
//  Copyright (c) 2015年 keso. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Book.h"

@interface Person : NSObject

@property (strong,nonatomic) NSString *Name;

@property (strong,nonatomic) Book  *Book;

@end

Book.h中的代碼:

//
//  Book.h
//  BugDemo
//http://www.cnblogs.com/xiaofeixiang/
//  Created by keso on 15/2/8.
//  Copyright (c) 2015年 keso. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Book : NSObject

@property (strong,nonatomic) NSString *BookName;

@end

Person中Book屬性的類型是Book類型,看下主函數中簡單調用:

      Person *person=[[Person alloc]init];
        [person setValue:@"FlyElephant" forKey:@"Name"];
        Book *book=[[Book alloc]init];
        person.Book=book;
        //路徑設置
        [person setValue:@"天涯明月刀" forKeyPath:@"Book.BookName"];
        NSLog(@"%@",[person valueForKey:@"Name"]);
        NSLog(@"%@",book.BookName);
        NSLog(@"%@",[person valueForKeyPath:@"Book.BookName"]);
        NSLog(@"%@",person.Book.BookName);

 最終的打印結果就是FlyElephant和天涯明月刀,需要注意的是一句就是需要先賦值一個對象給Person中Book屬性,不然是無法成功的:

   Book *book=[[Book alloc]init];
        person.Book=book;

 KVO觀察者模式

Key-Value Observing (KVO) 建立在 KVC 之上,能夠觀察一個對象的 KVC key path 值的變化,接下來的做的實例是在iOS中視圖的ViewDidLoad中實現的,跟KVC類似,不過可以監聽值的變化,實現起來很簡單addObserver添加觀察,observeValueForKeyPath觀察變化之后的事件,最后需要銷毀以下監聽事件,概念就這么簡單,具體的可以看一下:

新建博主(Blogger)和Article(文章)類:

Article.h聲明:

//
//  Article.h
//  KVDemo
//http://www.cnblogs.com/xiaofeixiang/
//  Created by keso on 15/2/8.
//  Copyright (c) 2015年 keso. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface Article : NSObject

@property (strong,nonatomic) NSString *ArticleName;

@end

Blogger.h代碼:

//
//  Bloger.h
//  KVDemo
//http://www.cnblogs.com/xiaofeixiang/
//  Created by keso on 15/2/8.
//  Copyright (c) 2015年 keso. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Article.h"

@interface Blogger : NSObject

@property (strong,nonatomic) NSString *Name;

@property (strong,nonatomic) NSString *Url;

@property (strong,nonatomic) Article *MyArticle;

@end

然后故事板中拖一個Button和一個TextField文本框,然后點擊的時候改變文本框的文字:

首先在ViewDidLoad中添加以下代碼,注意addObserver方法:

    _blogger=[[Blogger alloc]init];
    
    //設置名稱
    [_blogger setValue:@"FlyElephant" forKey:@"Name"];
    //設置Url
    [self.blogger setValue:@"http://www.cnblogs.com/xiaofeixiang" forKey:@"Url"];
    //設置觀察者,options通知的對象形式
    [self.blogger addObserver:self forKeyPath:@"Name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
    //設置文本
    [_myTextField setText:[_blogger valueForKey:@"Name"]];

   self.Article=[[Article alloc]init];
    
    [self.blogger setValue:self.Article forKey:@"MyArticle"];
    
    [self.blogger setValue:@"KVC和KVO的理解" forKeyPath:@"MyArticle.ArticleName"];

 按鈕點擊事件:

- (IBAction)blogObserver:(id)sender {
      NSLog(@"blogObserver");
    [self.blogger setValue:@"Keso" forKey:@"Name"];
}

OC中要實現KVO則必須實現NSKeyValueObServing協議,不過NSObject已經實現了該協議,直接重寫observeValueForKeyPath即可:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    NSLog(@"observeValueForKeyPath");
    if ([keyPath isEqualToString:@"Name"]) {
//         [_myTextField setText:[_blogger valueForKey:@"Name"]];
          [_myTextField setText:_blogger.MyArticle.ArticleName];
    }
}

 最后銷毀監聽事件:

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    [self.blogger removeObserver:self forKeyPath:@"Name"];
}

 最終實現效果:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM