Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I Use "weakSelf" In a dispatch Block?

I've heard that I should always use weakSelf in blocks to avoid retain cycles, but what about dispatch blocks? In this case, my method handles an error response from my server in the following code:

//handling server errors (particularly "Token Refresh Failed" ones)
-(void)handleServerErrorResponse:(NSString *)error {
    dispatch_async(dispatch_get_main_queue(), ^{
        UIAlertController *alertController = [DialogHelper getAlertForSimpleAuthError:error];
        if ([error isEqualToString:@"Your login session has expired"]) {
            [alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action)
            {
                [MyModelDataCenter emptyDataCenter];
                [MyAPIInterface sharedInstance].authToken = nil;
                NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
                [defaults removeObjectForKey:@"authToken"];
                [defaults removeObjectForKey:@"defaultUserObjectDictionary"];
                [defaults synchronize];
                [AuthenticationHelper sharedInstance].loggedInUser = nil;
                [self.navigationController popToRootViewControllerAnimated:YES];
            }]];
        }
        else {
            [alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:nil]];
        }
        [self presentViewController:alertController animated:YES completion:nil];
    });
}

Should I be using weakSelf in this block the same as I do it in other blocks?

like image 580
Rafi Avatar asked Jan 28 '16 04:01

Rafi


2 Answers

You need to use the weak-strong "dance" to avoid a retain cycle only when there's a persistent retain cycle. For that to happen, two conditions need to be met:

  • the Block is owned by an object that is referenced inside the Block
  • the owner doesn't release the Block before its own deallocation

If either one of those things is not true, there is no persistent retain cycle, and no problem.

In this case, neither is true. In general, Blocks put onto dispatch queues will not be subject to retain cycles, unless you're keeping the Block around in an ivar to reuse.

like image 73
jscs Avatar answered Nov 10 '22 10:11

jscs


Even I agree with Josh and have agreed from the very beginning, that there is no reason for weakifying self, if it is not necessary (the block is not hold by a referenced object), in the past the majority weakified self as default. (I think that the majority changes.)

However, there can be a reason to weakify self even there is no retain cycle:

Image that you have an instance object that is filled by a long-running block. It is possible that the instance object would die while the block is running, i. e. because the user deleted it. In such a case the block would fill an instance object that has no use anymore and is gone from your model, but still alive, because the block holds it. Weakifying it would free it and set the captured self to nil, what is easy to check and usually simply does nothing.

But I really do not think and have never thought that this scenario justifies up a rule of thumb "Weakify by default".

like image 44
Amin Negm-Awad Avatar answered Nov 10 '22 10:11

Amin Negm-Awad