使用ARC自动释放池和池排水

时间:2013-04-15 19:52:37

标签: ios cocoa-touch automatic-ref-counting

我想用ARC迁移此代码。

我知道我必须使用:

@autoreleasepool {}

但我有两个水池排水管的问题,我不知道该怎么做。

- (void)downloadImageToCache:(NSString*)_urlImage
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    if (!(_urlImage) || (_urlImage == nil)) 
    {
        [pool drain];
        return;
    }

    NSURL *url = [NSURL URLWithString:_urlImage];
    NSData *data = [[[NSData alloc] initWithContentsOfURL:url] autorelease];

    if (data != nil) 
    {
        ...do something...
    }
    else
    {

        ...do something...
    }
    [pool drain];
}

5 个答案:

答案 0 :(得分:2)

包裹整件事。不要担心退货。它会搞清楚。

即。编译器会将其转换为逻辑等效的:(或者你可以明确地清理逻辑)

- (void)downloadImageToCache:(NSString*)_urlImage
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  if (!(_urlImage) || (_urlImage == nil))
  {
    //[pool drain];
    //return;
  } else {

    NSURL *url = [NSURL URLWithString:_urlImage];
    NSData *data = [[[NSData alloc] initWithContentsOfURL:url] autorelease];

    if (data != nil)
    {
      ...do something...
    }
    else
    {  
      ...do something...
    }
  }
  [pool drain];
}

减少到:

- (void)downloadImageToCache:(NSString*)_urlImage {
  @autoreleasepool {
    if (_urlImage != nil) {

      NSURL *url = [NSURL URLWithString:_urlImage];
      NSData *data = [[[NSData alloc] initWithContentsOfURL:url] autorelease];

      if (data != nil) {
        // ...do something...
      } else {
        //...do something...
      }
    }
  }
}

或者(更少的嵌套缩进总是我的偏好):

- (void)downloadImageToCache:(NSString*)_urlImage {
  if (_urlImage == nil) {
    NSLog(@"[%@ %@] Error Message", NSStringFromClass([self class]), NSStringFromSelector(_cmd));
    return;
  }

  @autoreleasepool {

    NSURL *url = [NSURL URLWithString:_urlImage];
    NSData *data = [[[NSData alloc] initWithContentsOfURL:url] autorelease];

    if (data != nil) {
      // ...do something...
    } else {
      //...do something...
    }
  }
}

答案 1 :(得分:1)

你可以从自动释放池中“提前返回”,这将会释放 池中的所有对象:

- (void)downloadImageToCache:(NSString*)_urlImage
{
    @autoreleasepool {    
       if (!(_urlImage) || (_urlImage == nil)) 
       {
           // no need (not allowed) to call `drain`
           return;
       }

       NSURL *url = [NSURL URLWithString:_urlImage];
       NSData *data = [[[NSData alloc] initWithContentsOfURL:url] autorelease];

       if (data != nil) 
       {
           ...do something...
       }
       else
       {

           ...do something...
       }
       // no need (not allowed) to call `drain`
    }
}

答案 2 :(得分:0)

使用新的@autorelease块语法,当执行退出块时,池将被耗尽。所以你可以这样做:

- (void)downloadImageToCache:(NSString*)_urlImage
{
    @autoreleasepool {

        if (!(_urlImage) || (_urlImage == nil)) 
        {
            return; //leaves @autoreleasepool block, automatically drains
        }

        NSURL *url = [NSURL URLWithString:_urlImage];
        NSData *data = [[[NSData alloc] initWithContentsOfURL:url] autorelease];

        if (data != nil) 
        {
            ...do something...
        }
        else
        {

            ...do something...
        }
    } //leaves @autoreleasepool block, automatically drains
}

有关详细信息,请参阅AutoreleasePools

答案 3 :(得分:0)

也许:

- (void)downloadImageToCache:(NSString*)_urlImage
{
    @autoreleasepool {
        if (!(_urlImage) || (_urlImage == nil))
        {
            return;
        }

        NSURL *url = [NSURL URLWithString:_urlImage];
        NSData *data = [[NSData alloc] initWithContentsOfURL:url];

        if (data != nil)
        {

        }
        else
        {

        }
    }
}

来自:Apple Documentation

答案 4 :(得分:0)

这段代码中有两个排水管的唯一原因是因为它在第一次排水后立即返回。只需将代码包装在@autoreleasepool中,无论退出哪条返回路径,它都会在退出时消耗。