简体   繁体   中英

“Capturing 'self' strongly in this block is likely to lead to a retain cycle” using Reachability

I'm trying to edit a variable inside the Reachability block using Objective-C, this is the code:

- (void)testInternetConnection
{
    internetReachableFoo = [Reachability reachabilityWithHostname:@"www.google.com"];
    // Internet is reachable
    internetReachableFoo.reachableBlock = ^(Reachability*reach)
    {
        // Update the UI on the main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"Connessione ad Internet disponibile");
            checkConnection = YES;
            if(!lastConnectionState)
            {
                lastConnectionState = YES;
                if(doItemsDownload)
                    [self displayChoice];
            }
        });
    };

    // Internet is not reachable
    internetReachableFoo.unreachableBlock = ^(Reachability*reach)
    {
        // Update the UI on the main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"Connessione ad Internet non disponibile");
            checkConnection = NO;
            lastConnectionState = NO;
        });
    };

    [internetReachableFoo startNotifier];
}

Where checkConnection; & lastConnectionState; are 2 bool declared on my @interface; The problem is that accessing these variables and calling [self displayChoice]; inside this block gives me the warning: Capturing 'self' strongly in this block is likely to lead to a retain cycle

How can I possibly avoid this error? I tried declaring a WeakSelf and declaring self but I don't know how to do it for the bool variables

Capturing self strongly in a block is not always bad. If a block is being executed right away (UIView animate block for example) there is generally no risk.

The problem arises when self captures a block strongly and the block in turn captures self strongly. In this case self retains the block and the block retains self so neither can be released --> retain cycle!

To avoid this you need to capture self weakly in the block.

__weak typeof(self) = self;  // CREATE A WEAK REFERENCE OF SELF
__block BOOL blockDoItemsDownload = doItemsDownload;  // USE THIS INSTEAD OF REFERENCING ENVIRONMENT VARIABLE DIRECTLY
__block BOOL blockCheckConnection = checkConnection;
internetReachableFoo.reachableBlock = ^(Reachability*reach)
{
    // Update the UI on the main thread
    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"Connessione ad Internet disponibile");
        blockCheckConnection = YES;
        if(!lastConnectionState)
        {
            lastConnectionState = YES;
            if(blockDoItemsDownload)       // Use block variable here
                [weakSelf displayChoice];  // Use weakSelf in place of self
        }
    });
};

There is a cocoapod called libextobjc and what it allows you to do is quickly and cleanly weakify and strongify objects.

@weakify(self)
[someblock:^{
    @strongify(self)
}];

As long as you handle self you should be ok. I'm not 100% sure the BOOL values aren't an issue but I think you could do something like this:

BOOL x = YES;
@weakify(self, x)
[someblock:^{
    @strongify(self, x)
}];

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM