Ad

IOS - Should I Be Calling "weakSelf" In This Block?

- 1 answer

Okay so I might have not fully grasped WHEN I should use weakSelf in blocks. I know that it is done to prevent retain cycles and what not, but I heard there are some exceptions to this rule.

In the following code, I check to see if an API call failed due to the login session expiring, and then I attempt to re-authenticate the user and retry the API request that failed because of this issue by calling [self sendTask:request successCallback:success errorCallback:errorCallback]; in the re-authentication method's success block:

/*!
 * @brief sends a request as an NSHTTPURLResponse. This method is private.
 * @param request The request to send.
 * @param success A block to be called if the request is successful.
 * @param error A block to be called if the request fails.
 */
-(void)sendTask:(NSURLRequest*)request successCallback:(void (^)(NSDictionary*))success errorCallback:(void (^)(NSString*))errorCallback
{
    NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
    {
        [self parseResponse:response data:data successCallback:success errorCallback:^(NSString *error) {
            //if login session expired and getting "not authenticated" error (status 401)
            NSHTTPURLResponse *httpResp = (NSHTTPURLResponse*) response;
            if (httpResp.statusCode == 401) {
                NSLog(@"NOT AUTHENTICATED THO");
                AuthenticationHelper* auth = [AuthenticationHelper sharedInstance];
                NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
                //attempt to re-authenticate the user
                [AuthenticationHelper loginUser:[defaults stringForKey:@"username"] password:[defaults stringForKey:@"password"] successCallback:^(User* u)
                {
                    auth.loggedInUser = u;
                    NSLog(@"RE-AUTHENTICATION BUG FIX SUCCEEDED");
                    //attempt to re-try the request that failed due to
                    [self sendTask:request successCallback:success errorCallback:errorCallback];
                } errorCallback:^(NSString *error) {
                    NSLog(@"RE-AUTHENTICATION BUG FIX FAILED");
                }];
            }
            else {
                errorCallback(error);
            }
        }];
    }];
    [task resume];
}

Is this bad practice in that it can lead to a retain cycle? If so, why? Should I instead be using [weakSelf sendTask:request successCallback:success errorCallback:errorCallback]; assuming that I do MyAPIInterface *__weak weakSelf = self; beforehand?

Ad

Answer

In this example there would not be a retain cycle because self isn't holding a reference to the block. When the block completes, it will release its hold on self, and if that was the last reference, the instance will be deallocated, just as you would expect.

Ad
source: stackoverflow.com
Ad