__autoreleasing 修饰的变量不是局部变量;
它的生命周期由autoreleasepool负责;
+(Reachability*)reachabilityWithHostname:(NSString*)hostname
{
SCNetworkReachabilityRef ref = SCNetworkReachabilityCreateWithName(NULL, [hostname UTF8String]);
if (ref)
{
id reachability = [[self alloc] initWithReachabilityRef:ref];
return [reachability autorelease];
}
return nil;
}
局部变量由编译器插入的内存管理负责;只在作用域内有效,在步出作用域时会释放;
局部变量是强引用。
强引用的释放:
1、对象的析构释放;
2、作用域管理;
__autoreleasing
表示在autorelease pool中自动释放对象的引用,和MRC时代autorelease的用法相同。定义property时不能使用这个修饰符,任何一个对象的property都不应该是autorelease型的。
一个常见的误解是,在ARC中没有autorelease,因为这样一个“自动释放”看起来好像有点多余。这个误解可能源自于将ARC的“自动”和autorelease“自动”的混淆。其实你只要看一下每个iOS App的main.m文件就能知道,autorelease不仅好好的存在着,并且变得更fashion了:不需要再手工被创建,也不需要再显式得调用[drain]方法释放内存池。
以下两行代码的意义是相同的。
NSString *str = [[[NSString alloc] initWithFormat:@"hehe"] autorelease]; // MRC
@"hehe"// ARC
这里关于autoreleasepool就不做展开了,详细地信息可以参考官方文档或者其他文章。
在中主要用在参数传递返回值()和引用传递参数()的情况下。
__autoreleasing is used to denote arguments that are passed by reference (id *) and are autoreleased on return.
比如常用的NSError的使用:
NSError *__autoreleasing error;
(![data writeToFile:filename options:NSDataWritingAtomic error:&error])
{
@"Error: %@", error);
(在上面的writeToFile方法中error参数的类型为(NSError *__autoreleasing *))
errorstrong__autoreleasing
NSError *error;
// 编译器添加
(![data writeToFile:filename options:NSDataWritingAtomic error:&tempError])
{
// 编译器添加
@"Error: %@", error);
所以为了提高效率,避免这种情况,我们一般在定义error的时候将其(老老实实地=。=)声明为__autoreleasing类型的:
NSError *__autoreleasing error;
在这里,加上__autoreleasing之后,相当于在MRC中对返回值error做了如下事情:
*error = [[[NSError alloc] init] autorelease];
*error指向的对象在创建出来后,被放入到了autoreleasing pool中,等待使用结束后的自动释放,函数外error的使用者并不需要关心*error指向对象的释放。
ARC NSError **__autoreleasing比如下面的两段代码是等同的:
- (NSString *)doSomething:(NSNumber **)value
{
// do something
- (NSString *)doSomething:(NSNumber * __autoreleasing *)value
{
// do something
除非你显式得给value声明了__strong,否则value默认就是__autoreleasing的。
autorelease pool__autoreleasing比如NSDictionary的[enumerateKeysAndObjectsUsingBlock]方法:
- (void)loopThroughDictionary:(NSDictionary *)dict error:(NSError **)error
{
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
// do stuff
if (there is some error && error != nil)
{
*error = [NSError errorWithDomain:@"MyError" code:1 userInfo:nil];
}
}];
会隐式地创建一个autorelease pool,上面代码实际类似于:
- (void)loopThroughDictionary:(NSDictionary *)dict error:(NSError **)error
{
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop){
@autoreleasepool // 被隐式创建
{
if (there is some error && error != nil)
{
*error = [NSError errorWithDomain:@"MyError" code:1 userInfo:nil];
}
}];
// *error 在这里已经被dict的做枚举遍历时创建的autorelease pool释放掉了 :(
}
为了能够正常的使用*error,我们需要一个strong型的临时引用,在dict的枚举Block中是用这个临时引用,保证引用指向的对象不会在出了dict的枚举Block后被释放,正确的方式如下:
- (void)loopThroughDictionary:(NSDictionary *)dict error:(NSError **)error
// 加保证可以在内被修改
idid {
(there some error)
{
@"MyError"1
}
}]
(error != nil)
{
*error = tempError;
}
}
http://www.cnblogs.com/flyFreeZn/p/4264220.html