KVC
KVC
可以通过key
直接访问对象的属性,或者给对象的属性赋值(包括私有属性),这样可以在运行时动态的访问或修改对象的属性。
setValue forKey
Person *person = [[Person alloc] init];
[person setValue:@"小明" forKey:@"userName"];
NSString *name = [person getPrivateName];
NSLog(@"person private name:%@",name);
- 首先要调用对象的
setter
方法。 - 如果没有找到对应的属性,会找相应的_name成员变量。
- 如果还是没有找到,会执行
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
方法。可以在方法里做响应的属性名转换。如果没有实现此方法,则会异常崩溃。 - 如果想禁用KVC,
+ (BOOL)accessInstanceVariablesDirectly
中返回NO
,默认是返回YES
。
valueForKey
- 首先要调用对象的
getter
方法。 - 如果没有找到,会执行
- (id)valueForUndefinedKey:(NSString *)key
,在此方法里可以进行处理。如果没有实现此方法,则会异常崩溃。 - 如果想禁用KVC,
+ (BOOL)accessInstanceVariablesDirectly
中返回NO
,默认是返回YES
。
setValue:forKeyPath,valueForKeyPath
valueForKeyPath的值是一个路径(路径之间以点号 . 分割),比如数据成员就是对象自己,寻值过程就会向下深入下去。
autoreleasepool
main
函数中的autoreleasepool
从技术上看是非必要的,去掉没有什么关系。但为了严谨,为了让UIApplication
创建出来的自动释放的对象有自动释放池可添加,而不是依赖程序结束后的内存回收。
APP启动的时候会在主线程注册两个observer,一个监听即将进入runloop事件,一个监听runloop即将休眠和即将退出两个事件,在runloop即将休眠和即将退出的时候会销毁@autoreleasepool{}释放自动释放池,并释放autorelease对象。
实现方式
当自动释放池创建的时候,会调用objc_autoreleasePoolPush
方法,将POOL_SENTINEL
(哨兵对象)放入到栈顶。随后自动释放池内的对象会被加到栈顶中。
当自动释放池释放的时候,会调用objc_autoreleasePoolPop
方法,向自动释放池中的对象释放release
方法,直到POOL_SENTINEL
(哨兵对象)。
POOL_SENTINEL 只是 nil 的别名。
autoreleasepool
是由多个autoreleasePoolPage
以双向链表的形式链接起来的,当一个表满了,会自动创建下一个表,并双向链接起来。释放的时候,从最下面依次向上pop
,调用每个对象的release
,直到遇到标志位(POOL_SENTINEL)。
结构
autoreleasepool
实际上是一个结构体,结构如下
class AutoreleasePoolPage {
magic_t const magic; //AutoreleasePoolPage 完整性校验
id *next; //下一个存放autorelease对象的地址
pthread_t const thread; //所在线程
AutoreleasePoolPage * const parent; //父节点 (双向)
AutoreleasePoolPage *child; //子节点 (双向)
uint32_t const depth;
uint32_t hiwat;
};
内省(Introspection)
内省是面向对象语言和环境的一种特性,是在运行时(Run time)检查对象(object)的一种能力。可以通过内省,来判断对象在继承树上的位置,是否遵循特定的协议,是否可以响应特定的消息。
优点:
内省可以使面向对象程序更强壮高效,避免进行错误的消息派发,错误的假设对象。
最常见应用:
if (self.delegate && [self.delegate respondsToSelector:@selector(segmentDidChanged:)]) {
[self.delegate segmentDidChanged:type];
}
常用的几个内省方法:
-
isMemberOfClass
: 对象是否是某个类的对象。 -
isKindOfClass
: 对象是否是某个类或者某个类子类的对象。 -
isSubclassOfClass
: 某个类是否是另一个类的子类。 -
respondsToSelector
: 是否能响应某个方法。 -
conformsToProtocol
: 是否遵循某个协议。
class
方法和object_getClass
方法区别
- 实例的
class
方法就是直接返回object_getClass(self)
- 类的
class
方法直接返回self
-
object_getClass(类)
方法则返回元类。
网友评论