自动释放池块
自动释放池块是允许你放弃对一个对象的持有关系, 但可以避免它立即被回收的一个工具,它确保在块内创建的对象会在块完成时被回收, 本地的块可以用来尽早的释放其中的对象。
iOS应用的整个代码都在一个autoreleasepool
块中, 这意味着所有的对象autorelease
最后都会被回收,不会导致内存泄漏
int main(int argc, char * argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([UIAppDelegate class]));
}
}
在一些特定情况下使用autoreleasepool
:
- 在创建很对临时对象的循环时。在循环中使用
autoreleasepool
块可以为每个迭代释放内存。 - 创建一个线程时,每个线程都有他自己的
autoreleasepool
,主线程用自己的autoreleasepool
启动,对于其他任何自定义的线程必须自己创建autoreleasepool
变量限定符号
- __strong
这是默认的限定符,无需显示引人。只要有强引用指向,对象就会长时间驻留在内存中。可以将_strong理解为retain调用的ARC版本。
- __weak
这表明引用不会保持被引用对象的存活。当没有强引用指向对象时,弱引用会被置为nil。可将_ weak看作是assign操作符的ARC版本,只是对象被回收时,_ weak具有安全性, 指针将自动被设置为nil。
- _unsafe_unretained
与weak 类似,只是当没有强引用指向对象时,__unsafe_unretained 不会被置为nil。可将其看作assign操作符的ARC版本。
- __autoreleasing
__autoreleasing 用于由引用使用id *传递的消息参数。它预期了autorelease方法会在传递参数的方法中被调用。
使用这些限定符的语义如下:
TypeName * qualifier variable;
属性限定符
属性声明有两个新的特有关系限定符: strong和weak。
- strong
默认符,指定了
__strong
关系。
- weak
指定了
__weak
关系。
- assign
这不是新的限定符,但其含义发生了改变。在ARC之前,
assign
是默认的持有关系限定符。在启用ARC之后,assign
表示了_unsafe_unretatned
关系。
- copy
暗指了
__strong
关系。此外,它还暗示了setter中的复制语义的常规行为。
- retain
指定了__strong 关系。
- unsafe_unretained指定了
unsafe. unretained关系。
避免循环引用的规则
iOS中引用计数的最大陷阱在于,不能处理环状的引用关系,即Objective-C的循环引用。
-
避免大量的单例。具体来说,不要出现上帝对象( 如职责特别多或状态信息特别多的对象)。这是一个反模式,指代一种常见解决方案的设计模式,但很快产生了不良效果。日志器、埋点服务和任务队列这样的辅助单例都是很不错的,但全局状态对象不可取。
-
对子对象使用
__strong
。 -
对父对象使用
__weak
。 -
对使引用图闭合的对象(如委托)使用
__weak
。 -
对数值属性(
NSInteger
、SEL
、CGFLoat
等)而言,使用assign限定符。 -
对于块属性,使用
copy
限定符。 -
当声明使用
NSError **
参数的方法时,需要使用autoreleasing
, 并要注意用正确的语法:NSError * __autoreleasing *
。 -
避免在块内直接引用外部的变量。在块外面将它们
weakify
,并在块内再将它们strongify
。 -
进行必要清理时遵循以下准则:
★. 销毁计时器
★. 移除观察者(具体来说,移除对通知的注册)
★. 解除回调(具体来说,将强引用的委托设置为nil)
网友评论