cmii
cmii

Reputation: 3636

autoreleasepool and pool drain with ARC

I would like migrate this code with ARC.

I know I have to use :

@autoreleasepool {}

But I have a problem with the two pool drain, I don't know how to do.

- (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];
}

Upvotes: 0

Views: 2610

Answers (5)

bshirley
bshirley

Reputation: 8357

Wrap the whole thing. Don't worry about the returns. It will figure it out.

I.e. the compiler will convert it to the logically equivalent: (or you can explicitly clean up the logic)

- (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];
}

which reduces to:

- (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...
      }
    }
  }
}

or perhaps (fewer nested indentions are always my preference):

- (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...
    }
  }
}

Upvotes: 2

Fls'Zen
Fls'Zen

Reputation: 4654

The only reason there are two drains in this code is because it is returning early right after the first drain. Just wrap the code in @autoreleasepool, it will drain when it exits regardless of which return path is followed.

Upvotes: 0

Peteee24
Peteee24

Reputation: 530

Perhaps:

- (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
        {

        }
    }
}

From: Apple Documentation

Upvotes: 0

Lance
Lance

Reputation: 9012

With the new @autorelease block syntax, the pool will be drained when execution exits the block. So you can just do this:

- (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
}

See AutoreleasePools for more information

Upvotes: 0

Martin R
Martin R

Reputation: 539745

You can just "early-return" from the autorelease pool, that will release all objects from the pool:

- (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`
    }
}

Upvotes: 1

Related Questions