ARC会得出对象需要的生命周期,在编译的时候自动插入内存管理语句。编译器还会自动生成需要的dealloc函数,而不需要手动在dealloc中添加release。
使用ARC,将不再需要使用retain, release, autorelease。
对象属性默认使用strong存储。
使用规则:
1.不能显示调用dealloc
2.不能实现或调用retain, release, retainCount, autorelease, 使用@selector(retain)等形式调用也是不行。
3.可以实现dealloc方法,但是不能调用super dealloc,也不能释放对象属性,但可以把delegate置为nil,释放Core Foundation变量。
4.可以使用CFRetain, CFRelease
5.不能使用NSAllocateObject, NSDeallocateObject, 只能用alloc,运行时会管理dealloc。
6.不要使用C结构体对象,使用Objective C类来管理数据。
7.id和void *不能随意转换,必须使用特殊的转换方法,来明确的告诉编译器对象的生命周期。Objective C和Core Foundation对象间的转换需要通过函数,以参数的方式传人,转换成需要的类型。
8.不能再使用NSAutoreleasePool, 使用@autoreleasepool block代码块代替。它比NSAutoreleasePool效率更高。
9.不能使用内存区域,memory zones。 现在不必使用NSZone, Objective C运行时会忽略NSZone。
10.不能访问以new开头的函数。所以一般不能定义new开头的属性,如果必须使用new开头,必须指定不是new开头的get函数。
@property NSString *newTitle;//不行
@property (getter=theNewTitle) NSString *newTitle;//可以
ARC引入的一些修饰符:
strong:ARC默认的对象类型。
weak:类似assign,而且当对象没有引用时,自动赋值为nil.
__strong
__weak
__unsafe_unretained:当引用的地址被释放时,访问它会很危险。
__autoreleasing:传人函数的对象参数,当函数结束时,释放。
正确的修饰对象方法:
ClassName * qualifier variableName;
MyClass * __weak myWeakReference;
使用__weak时需要小心:
NSString * __weak string = [[NSString alloc] initWithFormat:@"abc%@",@"bcd"];
NSLog(@"string:%@", string);
虽然string是alloc的,并且后面有NSLog调用,但是没有一个对string的强引用,所以,第一行就已经释放,并赋值为nil。
所以__weak修饰的对象,必须首先有强引用,才能保住对象。
但是下面的代码是可行的:
NSError *error;
BOOL OK = [myObject performOperationWithError:&error];
if(!OK){
//能正常使用error
}
原因是编译器做了以下工作:
NSError * __strong error;
-(BOOL) performOperationWithError:(NSError * __autoreleasing *)error;
所以最后的代码是这样的:
NSError * __strong error;
NSError * __autoreleasing tmp = error;
BOOK OK = [myObject performOperationWithError:&tmp];
error = tmp;
if(!OK){
//...
}
ARC block代码块怎么避免循环引用:
MyViewController *myController = [[MyViewController alloc] init];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:myController animated:YES completion:^{
[myController release];
}];
处理方法:
1.使用__block,并且在block中把myController赋值为nil.
MyViewController * __block myController = [[MyViewController alloc] init];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
myController = nil;
}
2.使用__weak
MyViewController *myController = [[MyViewController alloc] init...];
// ...
MyViewController * __weak weakMyViewController = myController;
myController.completionHandler = ^(NSInteger result) {
[weakMyViewController dismissViewControllerAnimated:YES completion:nil];
}
更好的方法:
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...
}
};
堆栈变量被初始赋值为nil
- (void) myMethod {
NSString *name;
NSLog(@"name: %@", name);
}
-fobjc-arc/ -fno-objc-arc