回归基础:重温 Automatic Reference Counting (ARC)
1,ARC 是编译器做的事情(在编译期间插入内存管理相关代码)
ARC evaluates the lifetime requirements of your objects and automatically inserts appropriate memory management calls for you at compile time
2,即使是局部指针变量(属性变量、局部变量 are strong
by default),所指对象引用计数也将+1
ARC ensures that oldLastName
is not deallocated before the NSLog
statement.
- (void)takeLastNameFrom:(Person *)person { |
NSString *oldLastname = [self lastName]; |
[self setLastName:[person lastName]]; |
NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]); |
} |
3,ARC仅仅维护了内存管理,其它的资源还是要手动置空或释放
(记得scrollview滑动时候退出页面 某些系统(因老的sdk中delegate为assign?)会crash)
You do not have to (indeed you cannot) release instance variables, but you may need to invoke [systemClassInstance setDelegate:nil]
on system classes and other code that isn’t compiled using ARC.
4,new是可以作为属性字段名的,需要重写get方法
// Won't work: |
@property NSString *newTitle; |
// Works: |
@property (getter=theNewTitle) NSString *newTitle; |
5,正确的书写格式
ClassName * qualifier variableName; 不过编译器也兼容了非标准形式
MyClass * __weak myWeakReference; |
MyClass * __unsafe_unretained myUnsafeReference; |
6,注意 __weak 的使用(__weak的设计是为了解引用)
NSString * __weak string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]]; |
NSLog(@"string: %@", string); |
string是个空值
7,避免强引用 Use Lifetime Qualifiers to Avoid Strong Reference Cycles
避免循环引用 Two better options are to either use __weak
, or set the __block
value to nil
to break the retain cycle.
example 7-1
MyViewController *myController = [[MyViewController alloc] init…];
|
// ...
|
MyViewController * __weak weakMyViewController = myController;
|
myController.completionHandler = ^(NSInteger result) {
|
[weakMyViewController dismissViewControllerAnimated:YES completion:nil];
|
};
|
example 7-2
For non-trivial cycles, however, you should use:(对于重要的回路或循环 应该对weak加strong)
这里讨论一个问题:
(1)循环引用是编译时 插入相关代码 进行内存管理的
(2) 块内的 MyViewController *strongMyController = weakMyController; 仅在运行时起作用 (引起引用计数+1)
(3) 尽管仅是在block执行期间引起对象的引用计数+1,仍旧会引起延迟释放的问题(本该立刻释放的,延迟释放了,这也是不能容忍的)
(4) For non-trivial cycles 重要的回路 究竟是指啥?如果该block确定定在主线程执行 貌似没啥可后怕;当线程重重入、并发的时候 貌似有问题,
但是 线程重重入、并发 可通过加锁解决问题;MyViewController *strongMyController = weakMyController;这句话的目的 究竟很在?
留个疑问在此!!!
MyViewController *myController = [[MyViewController alloc] init…];
|
// ...
|
MyViewController * __weak weakMyController = myController;
|
myController.completionHandler = ^(NSInteger result) {
|
MyViewController *strongMyController = weakMyController;
|
if (strongMyController) {
|
// ...
|
[strongMyController dismissViewControllerAnimated:YES completion:nil];
|
// ...
|
}
|
else {
|
// Probably nothing...
|
}
|
};
|
8,outlets 修饰的属性 除了顶层的需要strong 子试图使用week修饰
The patterns for declaring outlets in iOS and OS X change with ARC and become consistent across both platforms. The pattern you should typicallyadopt is: outlets should be weak
, except for those from File’s Owner to top-level objects in a nib file (or a storyboard scene) which should be strong
.
9,临时变量初始化默认值为nil (不包括NSInteger、int等)Stack Variables Are Initialized with nil
Using ARC, strong, weak, and autoreleasing stack variables are now implicitly initialized with nil
好习惯:手动指定初始值 如 int i =0;另外 这int i =0 也是必须的;因为初始值并不是0 是不确定的
10,编译器并没有自动化管理引用计数 Core Foundation下对象
The compiler does not automatically manage the lifetimes of Core Foundation objects
__bridge
__bridge_retained or CFBridgingRetain /CFRelease
__bridge_transfer CFBridgingRelease