KVCiOS

iOS - Key Value Coding

2021-03-27  本文已影响0人  ienos

KVO 一种能够让对象的属性进行间接访问的机制


KVO 的实现由非正式协议 NSKeyValueCoding 拟定

只要继承了 NSObject 的对象都遵循 NSKeyValueCoding 协议,并提供了默认实现

参考链接

一、Using Key-Value Coding Compliant Objects

1、Accessing Object Properties

属性的三大类型

>> 通过 Key 或 KeyPath 访问属性

在 Swift 3 中新增 #keypath 表达式

>> Getting Attribute Values Using Keys

valueForUndefinedKey: - 默认抛出 NSUndefinedKeyException 异常,可重写该方法并自定义处理

>> Setting Attribute Values Using Keys

setValue:forUndefinedKey: - 默认抛出 NSUndefinedKeyException 异常,可重写该方法并自定义处理

当尝试给一个非对象类型赋值 nil 时,会发送 setNilValueForKey: 消息,默认抛出 NSInvalidArgumentException

>> eg: 通过属性的值(字符串)获取对应值的属性名的属性

- (id)tableView:(NSTableView *)tableview objectValueForTableColumn:(id)column row:(NSInteger)row
{
    id result = nil;
    Person *person = [self.people objectAtIndex:row];
 
    if ([[column identifier] isEqualToString:@"name"]) {
        result = [person name];
    } else if ([[column identifier] isEqualToString:@"age"]) {
        result = @([person age]);  // Wrap age, a scalar, as an NSNumber
    } else if ([[column identifier] isEqualToString:@"favoriteColor"]) {
        result = [person favoriteColor];
    } // And so on...
 
    return result;
}

- (id)tableView:(NSTableView *)tableview objectValueForTableColumn:(id)column row:(NSInteger)row
{
    return [[self.people objectAtIndex:row] valueForKey:[column identifier]];
}

2. Accessing Collection Properties

3. Using Collection Operators

valueForKeyPath: 的 key path 中嵌入集合运算符

Operator key path format

在三种场景下使用

>> Aggregation Operators

根据集合中的对象,输出单个值(NSNumber)

Operators Description Expression
@avg 平均值 NSNumber *transactionAverage = [self.transactions valueForKeyPath:@"@avg.amount"];
@count 数量 NSNumber *numberOfTransactions = [self.transactions valueForKeyPath:@"@count"];
@max 最大值 NSDate *latestDate = [self.transactions valueForKeyPath:@"@max.date"];
@min 最小值 NSDate *earliestDate = [self.transactions valueForKeyPath:@"@min.date"];
@sum 总和 NSNumber *amountSum = [self.transactions valueForKeyPath:@"@sum.amount"];

>> Array Operators

返回一个子集数组

Operators Description Expression
@distinctUnionOfObjects 获取 transactions 中 transaction.payee 的值,结果去重 NSArray *distinctPayees = [self.transactions valueForKeyPath:@"@distinctUnionOfObjects.payee"];
@unionOfObjects 获取 transactions 中 transaction.payee 的值 NSArray *payees = [self.transactions valueForKeyPath:@"@unionOfObjects.payee"];

>> Nesting Operators

返回 NSArray 或 NSSet,嵌套数组或集合使用

NSArray* moreTransactions = @[<# transaction data #>];
NSArray* arrayOfArrays = @[self.transactions, moreTransactions];

arrauOfArrays 是一个嵌套数组

Operators Description Expression
@distinctUnionOfArrays 获取数组中 transaction.payee 的值,结果去重 NSArray *collectedDistinctPayees = [arrayOfArrays valueForKeyPath:@"@distinctUnionOfArrays.payee"];
@unionOfArrays 获取数组中 transaction.payee 的值 NSArray *collectedPayees = [arrayOfArrays valueForKeyPath:@"@unionOfArrays.payee"];
@distinctUnionOfSets 获取集合中 transaction.payee 的值 NSSet 嵌套

4. Representing Non-Object Values

NSNumber 标量类型

Operators Description Expression
BOOL numberWithBool: boolValue (in iOS) charValue (in macOS)*
char numberWithChar: charValue
double numberWithDouble: doubleValue
float numberWithDouble: floatValue
int numberWithInt: intValue
long numberWithLong: longValue
long long numberWithLongLong: longLongValue
short numberWithShort: shortValue
unsigned char numberWithUnsignedChar: unsignedChar
unsigned int numberWithUnsignedInt: unsignedInt
unsigned long numberWithUnsignedLong: unsignedLong
unsigned long long numberWithUnsignedLongLong: unsignedLongLong
unsigned short numberWithUnsignedShort: unsignedShort

NSValue 结构体类型

Operators Description Expression
NSPoint valueWithPoint: pointValue
NSRange valueWithRange: rangeValue
NSRect valueWithRect: (macOS only). rectValue
NSSize valueWithSize: sizeValue
ThreeFloats floats = {1., 2., 3.};
NSValue* value = [NSValue valueWithBytes:&floats objCType:@encode(ThreeFloats)];
[myClass setValue:value forKey:@"threeFloats"];

5. Validating Properties

validateValue:forKey:error: (或者 validateValue:forKeyPath:error:

验证会出现三种结果:

  1. 验证 Value 对 Key 标识的属性有效,return YES
  2. 验证 Value 对 Key 标识的属性无效,并不对 Key 进行更改,return NO;并设置错误参数 NSError
  3. 验证 Value 对 Key 标识的属性无效,但创建了一个有效对象作为替换,return YES;错误对象保持不变;在返回之前,该方法会修改值引用以指向新的值对象。即使值对象是可变的也始终会创建一个新对象
Person* person = [[Person alloc] init];
NSError* error;
NSString* name = @"John";
if (![person validateValue:&name forKey:@"name" error:&error]) {
    NSLog(@"%@",error);
}

仅在 Objective-C 中使用

6. Accessor Search Patterns

>> Search Pattern for the Basic Getter

valueForKey:

>> Search Pattern for the Basic Setter

setValue:forKey:

>> Search Pattern for Mutable Arrays

mutableArrayValueForKey:

>> Search Pattern for Mutable Ordered Sets

mutableOrderedSetValueForKey:

>> Search Pattern for Mutable Sets

二、Key-Value Coding with Swift

在 Swift 中所有属性都是对象类型,将不会对非对象属性进行处理

三、Other Cocoa Technologies Rely on Key-Value Coding

上一篇 下一篇

猜你喜欢

热点阅读