所有内容引用自
《Objective-C 高级编程 iOS与OS X多线程和内存管理》
,加入了自己的部分理解。
本节小结,点小1
跳到底部[1]
第一节、思考方式
第二节、alloc/retain/release/dealloc实现
autorelease
就是自动释放。可类比C
的局部变量,超出作用域就会被废弃。
autorelease
具体使用如下:
1、生成并持有NSAutoreleasePool
对象
2、已分配对象调用autorelease
方法
3、废弃NSAutoreleasePool
对象
NSAutoreleasePool
对象的生命周期相当于C
局部变量的作用域。对于所有调用过autorelease
的对象,在废弃NSAutoreleasePool
对象时,都会调用release
。
一般情况下,程序主循环NSRunLoop
或其他程序可运行的地方,对NSAutoreleasePool
对象生成、持有和废弃处理。
只有在大量产生autorelease
对象,而NSAutoreleasePool
对象还没废弃,对象不能释放,造成内存不足的现象。比如读入大量图像的同时改变尺寸,就有必要自己管理NSAutoreleasePool
对象。
GNUstep
实现
1、autorelease
实现
- (id)autorelease{
[NSAutoreleasePool addObject:self];
}
可以看出,就是调用了一个addObject
类方法。
为了提高调用效率,使用IMP Caching
。
// 初始化时,把类名、方法名和函数指针都缓存起来
id autorelease_class = [NSAutoreleasePool class];
SEL autorelease_sel = @selector(addObject:);
IMP autorelease_imp = [autorelease_class methodForSelector:autorelease_sel];
使用时直接调用
- (id)autorelease{
(* autorelease_imp)(autorelease_class,autorelease_sel,self);
}
2、NSAutoreleasePool
实现
简化实现:
+ (void) addObject:(id)anObj{
NSAutoreleasePool *pool = 取得正在使用的NSAutoreleasePool对象;
if (pool != nil){
[pool addObject:anObj];
}eles{
NSLog(@"NSAutoreleasePool 对象非存在状态下调用autorelease");
}
}
🌰:
pool
就为当前正在使用的NSAutoreleasePool
对象。
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id obj = [[NSObject alloc] init];
[obj autorelease];
pool
废弃的时候,遍历数组中元素,执行release
。
苹果实现
objc4库的runtime/objc-arr.mm的实现
class AutoreleasePoolPage{
static inline void *push(){
// 相当于生成、持有NSAutoreleasePool类对象
}
static inline void *pop(void *token){
// 相当于废弃NSAutoreleasePool类对象
releaseAll();
}
static inline id autorelease(id obj){
// 相当于NSAutoreleasePool类的addObject类方法
AutoreleasePoolPage *autoreleasePoolPage = 取得正在使用的AutoreleasePoolPage实例;
autoreleasePoolPage->add(obj);
}
id *add(id obj){
// 将对象追加到内部数组
}
void releaseAll(){
// 调用内部数组中对象的release实例方法
}
}
// 对外暴露的方法
// 生成、持有AutoreleasePool对象
void *objc_autoreleasePoolPush(void){
return AutoreleasePoolPage::push();
}
// 废弃AutoreleasePool对象
void objc_autoreleasePoolPop(void *ctxt){
AutoreleasePoolPage::pop(ctxt);
}
// 添加对象到AutoreleasePool内部数组
id *objc_autorelease(id obj){
return AutoreleasePoolPage::autorelease(obj);
}
举个🌰:
// 等同于objc_autoreleasePoolPush()
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id obj = [[NSObject alloc] init];
// 等同于objc_autorelease
[obj autorelease];
// 等同于objc_autoreleasePoolPop
[pool drain];
小结
1、autorelease
本质是添加对象到NSAutoreleasePool
类的数组中
2、NSAutoreleasePool
生命周期结束后,遍历数组元素执行release
3、一般情况在主循环NSRunLoop
或其他可运行的地方,自动管理NSAutoreleasePool
生成、持有和废弃。
4、Cocoa
框架中很多类方法用于返回autorelease
对象
5、为提高执行效率,可以使用IMP Caching
-
😊假装是锚点的脚注 ↩
网友评论