/******************************************
* 今天对 “KVC(键值编码)”进行学习.收获如下:
* KVC是一种对对象属性更灵活的操作方式,这种方式以字符串为Key来间接操作对象的属性
* 1. 最基本的KVC是由NSKeyValueCoding协议提供支持操作属性的两个方法:
* 1⃣️存:“setValue:属性值对象 forKey:属性名字符串”
* 2⃣️取:“valueForKey:属性名字符串”
*
* 2. 执行机制:
* __
* | 1.程序首先寻找setter和getter方法,如找到则使用setter或getter
* | 2.如果没有setter或getter,则寻找名为_name的成员变量,直接取值或赋值
* < 3.如果没有名位_name的成员变量,则寻找名为name的成员变量,直接取值或赋值
* | 4.如果以上三条都没有找到,系统将会执行该对象的 “setValue:forUndefinedKey:”或“valueUndefinedKey:”方法
* |__ (两种方法实现的就是引发异常,致程序异常结束)
*
* 3. 如果前三条都没找到,系统默认的异常处理方法不合适(如并不想让程序结束),
* 可以覆写“setValue:forUndefinedKey:”和“valueUndefinedKey:”方法
*
* 4. 基本类型不可以赋值为nil,使用KVC也会默认使用setNilValueForKey:方法将程序异常结束;如不合适,可覆写。
*
* 5. KVC还可以操作“对象所包含的对象属性”(即复合属性),KVC机制将其称为Key路径。使用如下两个方法:
* 1⃣️存:setValue:属性值对象 forKeyPath:Key路径
* 2⃣️取:valueForKeyPath:Key路径
*
*******************************************/
#import <Foundation/Foundation.h>
/****************** LBXYApple类 **********************/
@interface LBXYApple : NSObject
{
@package
NSString* name;
NSString* _name;
}
@end
@implementation LBXYApple
{
double price;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
NSLog(@"您尝试设置的Key:%@ 并不存在!您尝试设置的value为:%@.",key,value);
}
@end
/*************************v************************/
/****************** LBXYAppleTree类 **********************/
@interface LBXYAppleTree : NSObject
@property(nonatomic, strong) LBXYApple* app;
@end
@implementation LBXYAppleTree
@end
/*********************************************************/
int main(int argc, const char * argv[])
{
@autoreleasepool
{
LBXYApple* apple = [[LBXYApple alloc] init];
[apple setValue:@"大苹果" forKey:@"name"]; //由于KVC默认机制,没有setter方法,会将@“大苹果”赋值给_name成员变量。
NSLog(@"apple的name是:%@",apple->name); //初始化后为nil,所以仍为nil
NSLog(@"apple的_name是:%@",apple->_name); //使用KVC对_name赋值为@“大苹果”
[apple setValue:[NSNumber numberWithDouble:5.2] forKey:@"price"];
NSLog(@"apple的price为: %@ 元/500g",[apple valueForKey:@"price"]);
[apple setValue:@"ABC" forUndefinedKey:@"age"]; //向不存在的属性发送KVC赋值消息,触发覆写的setValue:forUndefinedKey:方法.
LBXYAppleTree* tree = [[LBXYAppleTree alloc] init];
tree.app = [[LBXYApple alloc] init]; //初始化tree对象包含的app对象
[tree setValue:@"我是苹果数上的一颗苹果" forKeyPath:@"app.name"]; //使用Key路径为“tree对象包含的app对象的name属性”赋值
NSLog(@"苹果树上有颗苹果名字叫:%@",[tree valueForKeyPath:@"app.name"]);//使用Key路径对“tree对象包含的app对象的name属性”取值
}
return 0;
}