[iOS] ・KVC再学習

KVC


KVC の完全な名前は KeyValueCoding で、一般に「キー値コーディング」として知られています。これは、キーを介して特定の属性にアクセスできます。

KVC は、そのプロパティ メソッドまたはメンバー変数に間接的にアクセスするためのメカニズムを提供します。対応するプロパティ メソッドまたはメンバー変数には、文字列を介してアクセスできます。

これは、Setter および Getter メソッドを呼び出してアクセスする代わりに、オブジェクトのプロパティに間接的にアクセスするメカニズムを提供する非公式のプロトコルです。KVO は、KVC に基づく主要な技術の 1 つです。

KVC で一般的に使用される 4 つの方法

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

キーとキーパスの違い

key: 現在のクラスの属性のみを受け入れることができます。これは、それが独自のものであるか、親クラスから継承されたものであるかに関係なく、
keypath現在のクラスの属性を受け入れることに加えて、現在のクラスの属性の属性も受け入れることができます。つまり、関係チェーンを受け入れることができます

使用法:

        //key的设值取值
        Person *personPath = [[Person alloc] init];
        [personPath setValue:@"I am Father" forKey:@"name"];
        NSLog(@"%@", [personPath valueForKey:@"name"]);

出力結果:
ここに画像の説明を挿入

        //keypath的设值取值
        personPath.son = [[PersonSon alloc] init];
        [personPath setValue:@"I am Son" forKeyPath:@"son.sonName"];
        NSLog(@"%@", [personPath valueForKeyPath:@"son.sonName"]);
        NSLog(@"%@", personPath.son.sonName);

出力結果:
ここに画像の説明を挿入

一括ストア値操作

KVC指定されたセットに従ってセットをkey取得しvalue、それを辞書の形式で返すことができる、より強力な関数もあります。

- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;

一括代入操作

同様に, バッチ操作も KVC を介して実行できます.setValuesForKeysWithDictionary:オブジェクトを使用してメソッドを呼び出す場合, パッケージ化されたkey辞書を渡すことができます. KVC はvalueすべてのデータを属性名に従って辞書とkey照合し、value値をオブジェクトの属性。

- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;

サンプルコード:

        //逐个赋值
        Person *personFirst = [[Person alloc] init];
        [personFirst setValue:@"zxb" forKey:@"name"];
        [personFirst setValue:@20 forKey:@"age"];
        [personFirst setValue:@"男" forKey:@"sex"];
        NSLog(@"name = %@, age = %ld, sex = %@",personFirst.name, (long)personFirst.age, personFirst.sex);
        
        //通过字典赋值取值
        NSDictionary *dictionaryFirst = [personFirst dictionaryWithValuesForKeys:@[@"name", @"age", @"sex"]];
        NSLog(@"dictionaryFirst = %@", dictionaryFirst);
        
        NSDictionary *dictionarySecond = @{
    
    @"name":@"zzy", @"age":@11, @"sex":@"女"};
        Person *personSecond = [[Person alloc] init];
        [personSecond setValuesForKeysWithDictionary:dictionarySecond];
        NSLog(@"name = %@, age = %ld, sex = %@",personSecond.name, (long)personSecond.age, personSecond.sex);

出力結果:
ここに画像の説明を挿入

辞書モデルの相互変換

model属性と が一致しない場合dic、メソッドをオーバーライドできます-(void)setValue:(id)value forUndefinedKey:(NSString *)key

//StudentModel.h
@interface StudentModel : NSObject

@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *age;
@property (nonatomic, strong) NSString *studentSex;

@end

//StudentModel.m
@implementation StudentModel

- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
    
    
    if ([key isEqualToString:@"sex"]) {
    
    
        self.studentSex = (NSString *)value;
    }
}

@end

//main.m
        //字典模型相互转化
        NSDictionary *dictionary = @{
    
    @"name":@"stu1", @"age":@66, @"sex":@"nv"};
        StudentModel *model = [[StudentModel alloc] init];
        [model setValuesForKeysWithDictionary:dictionary];
        NSLog(@"model.name:%@",model.name);
        NSLog(@"model.age:%@",model.age);
        NSLog(@"model.sex:%@",model.studentSex);
        
        NSDictionary *tempModelDictionary = [model dictionaryWithValuesForKeys:@[@"name", @"age", @"studentSex"]];
        NSLog(@"tempModelDictionary : %@", tempModelDictionary);

出力結果:
ここに画像の説明を挿入

KVCのその他の方法

// 默认返回YES,表示如果没有找到Set<Key>方法的话,会按照_key,_iskey,key,iskey的顺序搜索成员,设置成NO就不这样搜索
+ (BOOL)accessInstanceVariablesDirectly;

// KVC提供属性值正确性验证的API,它可以用来检查set的值是否正确、为不正确的值做一个替换值或者拒绝设置新值并返回错误原因。
- (BOOL)validateValue:(inout id __nullable * __nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;

// 这是集合操作的API,里面还有一系列这样的API,如果属性是一个NSMutableArray,那么可以用这个方法来返回。
- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key;

// 如果Key不存在,且KVC无法搜索到任何和Key有关的字段或者属性,则会调用这个方法,默认是抛出异常。
- (nullable id)valueForUndefinedKey:(NSString *)key;

// 和上一个方法一样,但这个方法是设值。
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;

// 如果你在SetValue方法时面给Value传nil,则会调用这个方法
- (void)setNilValueForKey:(NSString *)key;

// 使用字典为Model赋值
- (void)setValuesForKeysWithDictionary:(NSDictionary<NSString *, id> *)keyedValues;

// 输入一组key,返回该组key对应的Value,再转成字典返回,用于将Model转到字典。
- (NSDictionary<NSString *, id> *)dictionaryWithValuesForKeys:(NSArray<NSString *> *)keys;

KVC原理の探究

setValue:forKey:原則(KVC割り当て原則)

  • まず、の順にメソッドを検索し、メソッドを見つけて直接呼び出して代入しますsetKey_setKey
  • メソッドが見つからない場合は、呼び出します+ (BOOL)accessInstanceVariablesDirectly(メンバー変数に直接アクセスできるかどうか、デフォルトでは YES が返されます)。
  • accessInstanceVariablesDirectlyメソッドが YES を返した場合、メンバー変数を_key_isKey、の順に検索しkey、直接代入を見つけ、見つからない場合は例外をスローします。isKeyNSUnknowKeyExpection
  • accessInstanceVariablesDirectlyメソッドが を返す場合NO、それが呼び出されsetValue:forUndefinedKey:、NSUnknownKeyExpection 例外がスローされます。

写真の説明を追加してください

メソッドはここに記載されていますsetValue:forUndefinedKeyが、このメソッドの使用方法は?

iOS の KVC (キー値コーディング) では、オブジェクトの setValue:forKey: メソッドが呼び出されたが、値を格納するための対応するプロパティまたはインスタンス変数がオブジェクトにない場合、オブジェクトの setValue:forUndefinedKey メソッドがトリガーされます。このメソッドの機能は、実行時に新しいプロパティまたはインスタンス変数をこのオブジェクトに動的に追加し、この値を新しく追加されたプロパティまたはインスタンス変数に格納することです。
クラスが setValue:forUndefinedKey: メソッドを実装していない場合、デフォルトで例外がスローされることに注意してください。したがって、KVC の使用時にプログラムがクラッシュし、エラー メッセージに文字列「NSUnknownKeyException」が含まれている場合は、おそらくこの理由によるものです。

valueForKey:原則(KVC価値原則)

  • getKeyまず、 、key、の順にメソッドを検索しisKey_key直接呼び出し値を見つけます。
  • 見つからない場合は+ (BOOL)accessInstanceVariablesDirectly戻り値を確認し、NO が返された場合はNSUnknowKeyExpection直接例外をスローします。
  • 返された場合はYES、メンバー変数を、 、_keyの順に検索し値を見つけます。_isKeykeyisKey
  • 見つからない場合に呼び出すvalueForUndefinedKey:NSUnknowKeyExpection例外をスローします。
    写真の説明を追加してください

予防

  • keyの値は正しい必要があります。スペルが間違っていると、例外が発生します。
  • keyの値が未定義の場合、valueForUndefinedKey:このメソッドが呼び出されます. このメソッドを自分で記述した場合、keyの値が間違っていると、ここで呼び出されます.
  • クラスは繰り返し入れ子にできるので、このパスに沿ってアクセスできるように、 という記号で1つずつつなげるkeyPathという考え方があります。keyPathkey
  • NSArray/ NSSetetc すべて KVC をサポートします。
  • KVCカスタム型のプライベート メンバーを介してアクセスできます。
  • そうであれば非オブジェクト値を渡すと、KVCがメソッドをnil呼び出します。このメソッドを書き直して、エラーの受け渡しを回避できます。オブジェクトはこのメソッドを呼び出さず、エラーを直接報告します。setNIlValueForKeynil
  • 非オブジェクトを扱う場合、setValue代入するオブジェクトが基本型の場合、値をNSNumberorNSValue型にカプセル化する必要があります. valueForKeytype のオブジェクトが返された場合、基本データ型もoridにカプセル化されます. 値をオブジェクトに自動的にラップすることは可能ですが、そうではありません。値の型を/型に手動で変換して渡す必要がありますNSNumberNSValuevalueForKeysetValue:forKey:NSNumberNSValueinitWithBool:(BOOL)value

おすすめ

転載: blog.csdn.net/m0_62386635/article/details/130347385