0

I have read the great article write by benzado that using block will cause memory leak if we have a class variable retain the block itself, and the block retain "self", that cause a retain cycle.

How do I avoid capturing self in blocks when implementing an API?

But I don't understand why using GCD will cause the same problem? functions like dispatch_async() looks like a local variable for me that shouldn't be captured by the class itself?

And the official document said that we should put autorelease in the blocks to ensure that our objects are released in time.

In most of my IOS project, I use GCD like this:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,(unsigned long)NULL), ^(void) {

    NSDictionary *resultDic = [MyService loadData];

    dispatch_async(dispatch_get_main_queue(), ^{
        [self.delegate useData:resultDic];
    });
});

Now I need to change all of them to

__block MyClass *blockSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,(unsigned long)NULL), ^(void) {

    @autoreleasepool{
        NSDictionary *resultDic = [MyService loadData];

        dispatch_async(dispatch_get_main_queue(), ^{

            @autoreleasepool{
                [blockSelf.delegate useData:resultDic];
            }
        });

    }
});

??

It looks dirty. Does anyone have a clue how to do it in a right way?

BTW, if I called some functions in the block and use "self" or "self.delegate" in that functions, does it mean that I need to change all of then to something else? (and I don't know what to do to fix it)

FYI, my IOS project is builded in IOS8.1 and non-ARC environment.

Community
  • 1
  • 1
林鼎棋
  • 1,995
  • 2
  • 16
  • 25
  • 2
    Slightly off-topic: You should do yourself a favor and switch to ARC. – Aaron Brager Feb 06 '15 at 02:37
  • I'm not sure you've understood the post you link to. It doesn't mention `@autoreleasepool` because that doesn't break retain cycles. – Tommy Feb 06 '15 at 02:41
  • it's legacy code and I can't do anything but let it remain non-ARC orz. Yes, the @autoreleasepool issue is mentioned in the official article by Apple Developer Document instead of the link I put here. – 林鼎棋 Feb 06 '15 at 07:57

1 Answers1

3

@autoreleasepool isn't needed.

To the block you pass to dispatch_async, block would be copied(Block_copy) to the heap, but it would be released(Block_release) immediately after it is called. So no retain cycle there.

To all the block you are using in your project, if self has a strong reference to the block or a strong reference chain to the block, you should use __block MyClass *blockSelf = self; to avoid retain cycle.

Note: __block MyClass *blockSelf = self; works in non-ARC, if you migrate to ARC, use __weak instead.

KudoCC
  • 6,912
  • 1
  • 24
  • 53