自动引用计数
目前创新互联建站已为成百上千家的企业提供了网站建设、域名、虚拟空间、网站托管运营、企业网站设计、启东网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
上面的那样处理过程,使得问题变得更加复杂,因为你总是要记住内存管理的规则,你需要知道什么时候在代码中加入retain,release,或者autorelease。因此,在新版Xcode(Xcode4.2),苹果发布了一个新的机制,使得retain,release,和autorelease自动执行。上面所有的策略依然可以应用在新版本的代码中。但是Xcode会为你添加内存管理需要的代码。
为了给你一个快速的了解,我重新编写Listing 7.1和Listing 7.2代码。
Listing 7.4.Rewrite Code for the New ARC mechanism
For Listing 7.1:
- (void)doSomething {
NSObject *obj = [[NSObject alloc] init];
NSLog(@"obj: %@", obj);
}
For Listing 7.3:
- (NSObject *)getObj {
NSObject *obj = [[NSObject alloc] init];
return obj;
}
就是这样!不在需要release或autorelease。当你编译代码的时候,Xcode会自动的为你添加release/autorelease相关代码。在编译器添加这些调用后,代码就和Listing 7.1和Listing 7.3一样了。
如何在Xcode中设置你的工程?
进入你的工程的settings,查找Objective-C Automatic ReferenceCounting是否设置为YES。你可以在图7-2的看到设置行的位置:
如果有一个已经使用了retain/release/autorelease的工程,你可以使用Xcode的migration工具来删除这些不需要的代码,如图7-3 。
ARC策略
你需要遵守一些新的规则来确保你的工程兼容ARC:
你不能使用或调用旧的内存管理方法:retain,release,autorelease和retainCount。你可以复写dealloc方法做任何你需要清理的工作,但是你不能调用dealloc方法,例如[super dealloc]是不允许的。
在构建属性的时候,这个规则也是强制要求的:
@property (nonatomic, retain) NSString *myName; // 这是不允许的
在c中不能使用对象指针,这会导致很多问题,如果你想在你的工程中集成c代码,如第9章所描述。你不能使用NSAutoreleasePool对象,必须使用@autoreleasepool。
不能使用:
NSAutoreleasePool *myPool = [[NSAutoreleasePool alloc] init];
// your code here
[pool release];
必须使用:
@autoreleasepool {
// your code here
}
ARC新的修饰符
根据新的ARC策略,你现在需要包含新的生命周期的修饰符来运用新的ARC规则。
strong:这个表示你想保持一个变量的强引用。只要有对象A的一个强引用,对象A就不会deallocated。
weak:这个和assign类似,如果你只是想要保持一个对象的引用,而又不想显示的拥有它。因此,你不需要管理这个对象的生命周期。一个比较好的情况是:如果对象A有对象B的一个弱引用,如果对象B被deallocated,那么这个引用会变成nil。这样是比较安全的,因为你不会拥有一个已经deallocated对象的引用。
unsafe_unretained:这个和weak类似,他们的不同之处是:对象A有对象B的一个引用,如果对象B被deallocated了,那么对象A的引用就会指向一个deallocated对象,这样会导致应用程序崩溃。
autoreleaseing:如果你有一个方法需要引用传递的参数,你可以考虑这个修饰符。当返回的时候,方法会负责autorelease这个参数。
对象属性
现在,你需要改变对象属性的声明。不要在使用之前版本的旧的内存管理机制:@property (retain) NSString *myString,现在有一个新的规则。
如果你想拥有一个对象的所有权
// This is similar to @property (retain) NSString *myString
@property(strong) NSString *myString;
如果你只是要持有一个对象的引用,而不是它的所有权
// This is similar to @property (assign) UIViewController *myViewController;
// except that if myViewController object is deallocated,
// the reference becomes nil.
@property(weak) UIViewController*myString;
注意:如果你想要你的应用运行在iOS4,你不能使用weak。你需要使用unsafe_unretained然后自己设置引用为nil。 |
变量声明
为了在方法内部使用这些修饰符,你需要在它的前面添加__(两个下划线)。例如,你可以使用__strong或__weak。在方法中,__strong是默认的修饰符。
使用__strong修饰符能确保你的对象一直存在直到方法结束,同时要小心使用__weak或__unsafe_unretained。如果没有强引用指向你的对象,你的对象会立即崩溃。例如:
NSString __weak *myString = @"hello world";
NSLog (@"myString: %@", myString);
将会打印(null),因为在打印时,已经没有强引用指向它。
__autoreleasing修饰符用来给方法接收一个引用传递的参数。
- (BOOL)performTaskWithError:(NSError *__autoreleasing *)error;
你可以正常的调用它:
NSError *error = nil;
[self performTaskWithError:&error];
默认,error对象声明为强引用,但是编译器会添加代码使得调用方法[self performTaskWithError:&error] ;
注意:对于返回对象的所有方法,同时没有包含new,alloc或copy,对象在返回是会自动的变为autoreleased。 |