一、kvc
kvc键值编码:通过Key名直接访问对象的属性,或者给对象的属性赋值。而不需要调用明确的存取方法。
这样就可以在运行时动态地访问和修改对象的属性。iOS开发中的黑魔法之一。
Animal *cat= [[Animal alloc] init];
[cat setValue:@"tom" forKey:@"name"];
当调用[cat setValue:@"tom" forKey:@"name"];
时,底层的执行机制如下:
- 程序优先调用
setName:
属性值方法, - 如果没有找到
setName:
方法,那么KVC机制会检查该对象+ (BOOL)accessInstanceVariablesDirectly
方法有没有返回YES,默认该方法会返回YES,如果你重写了该方法让其返回NO的话,那么在这一步KVC会执行setValue:forUndefinedKey:
方法。所以KVC机制会搜索该类里面有没有名为_name
的成员变量,无论该变量是在类接口处定义,还是在类实现处定义,也无论用了什么样的访问修饰符,只在存在以_name
命名的变量,KVC都可以对该成员变量赋值。
如果该类即没有setName:
方法,也没有_name
成员变量,KVC机制会搜索_isName
的成员变量。 - 如果都没有找到,那么也会执行到
setValue:forUndefinedKey:
方法,如果没有实现该方法,则会crash抛出异常。
1、dynamic
@interface Animal : NSObject
@property (nonatomic, copy)NSString *age;
@end
@implementation Animal
@dynamic age;
@end
如果我们在实现implementation
中,写了@dynamic age;
,那么编译器既不会生成setter和getter方法,也不会生成_age
的成员变量。调用setValue: forKey:
一定会异常
2、synthesize
synthesize的作用就是取别名,并生成setter和getter方法;由编译器自动添加
@interface Animal : NSObject
@property (nonatomic, copy)NSString *age;
@end
@implementation Animal
@synthesize age = _sff;
@end
二、反射机制
反射这个概念在oc中其实是比较模糊的,那么oc的反射机制理解为通过一个字符串,找到对应的class和selector的过程。
用处的话主要是
因为这些转化是发生在运行时的,所以我们可以用这个机制来动态的获取类、方法或属性,从而动态的创建类对象、调用方法、或给属性赋值、判断类型等。
Class class = NSClassFromString(@"OBViewController");
OBViewController *vc = [[class alloc] init];
SEL selector = NSSelectorFromString(@"getDate");
[vc performSelector:selector];
以及上面的kvo中的调用setValue: forKey:
也是一种运用