__autoreleasing 与 局部变量

__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]方法释放内存池。

311645216448780.png

以下两行代码的意义是相同的。

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 

原文地址:https://www.cnblogs.com/feng9exe/p/10383633.html