IOSにおけるKVCとKVOの応用解析


IOSにおけるKVCとKVOの応用解析


一、NSKeyValueCoding(KVC)


1、一例から導入する


KVCキー値符号化はObject−Cが我々に提供するメンバー変数に値を付与する方法である.その方法を検討する前に、小さな例を見てみましょう.
まず、データモデルモデルクラスを作成します.
//.h 
#import <Foundation/Foundation.h>
@interface Model : NSObject
{
    @public//   
    NSString * str;
}
@end

他のファイルではstrを割り当て、値を取る2つの方法があります.
    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メソッドを用いる効果は同じである.

2、KVC関連関数方法の詳細


上記の例を通して、KVCが何をしているのかを簡単に理解することができます.以下はいくつかの一般的な方法です.
+ (BOOL)accessInstanceVariablesDirectly;
この方法はスイッチのようなもので、デフォルトではYESで、KVC方式の付与をサポートしていることを示しています.サブクラスで書き換えることもできます.NOに戻ると、KVCを行うと異常が放出されます.
- (id)valueForKey:(NSString *)key;
キーによる値の取得
- (void)setValue:(id)value forKey:(NSString *)key;
文字列キーでメンバー変数に値を割り当てる
- (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;
上記の2つの方法はそれぞれパス賦値と取値によって行われ、データ構造は地図に似ています.例えば、modelクラスにメンバー変数model 2があり、model 2クラスに文字列があり、以下のように値を賦値することができます.
//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;
上の3つの方法は前と似ていますが、パスから値を取っただけです.
- (id)valueForUndefinedKey:(NSString *)key;
このメソッドは、実行時に作成されたように、事前に定義されていないメンバー変数の値を取得できます.次のメソッドは、定義されていないメンバー変数に値を付与します.
- (void)setValue:(id)value forUndefinedKey:(NSString *)key;
注:この2つのメソッドのデフォルトのインプリメンテーションは例外を放出し、サブクラスは書き直さなければ使用できません.
- (void)setNilValueForKey:(NSString *)key;
メンバー変数をnilに設定
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;
キー値に基づいてキー値対辞書を取得
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
辞書でメンバー変数の割り当てに同意し、よく使用されます.

二、NSKeyValueObservingCustomization(KVO)


KVOはメッセージ傍受メカニズムであり,ある量が変化したときにメッセージを傍受者に伝送できるため,伝達値,インタフェースの低結合などの論理に広く用いられている.KVOメカニズムの核心は以下の3つの方法である.
- (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;
この2つの方法は、リスナーを削除するために使用されます.
- (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);
    }
}

学習利用へようこそ