1

I have the following code to download an image:

  imageRequest = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:magazineItem.contentURL]];
  __weak ASIHTTPRequest *weakRequest = imageRequest;

  __block typeof (self) bself = self;
  [imageRequest setCompletionBlock:^{
    if (weakRequest.responseStatusCode == 200) {
      bself.imageData = weakRequest.responseData;
      [[DataAccessLayer sharedInstance] storeTemporaryContentData:bself.imageData url:magazineItem.contentURL];
      bself.contentImage = [UIImage imageWithData:bself.imageData];
      if (bself.contentImage != nil) {
        if (bself.magazineItem.presentationStyle.intValue != -1) {
          [bself setPresentationStyle:bself.magazineItem.presentationStyle.intValue];
        }
        else {
          [bself setPresentationStyleForImage:bself.contentImage];
        }
      }
      else
        [bself.delegate contentItemViewUnavailable:bself];
    }
    else {
      [bself.delegate contentItemViewUnavailable:bself];
    }
  }];

  [imageRequest setFailedBlock:^{
    if (weakRequest.error.code == 4)
      return;
    [bself.delegate contentItemViewUnavailable:bself];
  }];

  [imageRequest startAsynchronous];

And though I'm using a __block typeof (self) identifier to pass the self into the block, it still gets retained. I also have tried __weak MyClassName *bself = self; and it still gets into retain cycle. It seem I'm missing something here, can anyone fill me up with what exactly am I doing wrong?

For reference imageRequest is a __strong iVar in my .m file category.

Thanks in advance.

Eugene
  • 10,006
  • 4
  • 37
  • 55
  • did you set imageRequest strong? @propert(nonatomic,strong) ASIHTTPRequest *imageRequest; – janusfidel Jul 03 '12 at 11:29
  • Yes, the iVar is strong by default, but I'm using another request as a weak reference to the strong one, keeping it in memory for further operations like cancel. – Eugene Jul 03 '12 at 11:30

2 Answers2

1

try

__block __unsafe_unretained typeof (self) bself = self;

-- EDIT --

The comment that actually solved the issue

when accesing ivars, do it using bself.property. If you access your ivars directly it will get a retain cycle.

Eugene
  • 10,006
  • 4
  • 37
  • 55
javieralog
  • 1,337
  • 9
  • 10
  • Compiler reports an error: "The type 'typeof (self)' (aka 'MyClass *const __strong') already has retainment attributes set on it" – Eugene Jul 03 '12 at 11:35
  • change typeof(self) with MyClassName* – javieralog Jul 03 '12 at 11:38
  • Changed as you have suggested. The class still gets into a retain cycle. Any other suggestions? – Eugene Jul 03 '12 at 11:41
  • are you accessing ivars in your block? – javieralog Jul 03 '12 at 11:43
  • Yes, I have a few properties. imageData is a strong property, magazineItem too, contentImage as well. But I am accessing them via bself, so can this be an issue? – Eugene Jul 03 '12 at 11:45
  • when accesing ivars, do it using bself.property. If you access your ivars directly it will get a retain cycle: [[DataAccessLayer sharedInstance] storeTemporaryContentData:bself.imageData url:magazineItem.contentURL]; – javieralog Jul 03 '12 at 11:48
  • I'm not sure I got you there. When I remove the bself. from in front of my iVars it says that "capturing self strongly will lead to retain cycle", if I'm using self. in front of the iVars the warning disappears but retain cycle is still in there. So how do I access my iVars in block without triggering a retain? – Eugene Jul 03 '12 at 11:54
  • you should use bself.magazineItem instead of magazineItem – javieralog Jul 03 '12 at 11:57
  • That actually did it. Thank you very much! – Eugene Jul 03 '12 at 12:08
  • or you can do it using `bself->ivar` (analogous to how `ivar` is the same as `self->ivar`) – newacct Jul 03 '12 at 18:06
1

As suggested here Generic typeof for weak self references

__weak __typeof__((__typeof__(self))self) bself = self
Community
  • 1
  • 1
Denis Mikhaylov
  • 2,035
  • 21
  • 24