0

In the following code, how would you avoid nested blocks increasing the retain count of 'self'.

This is how I avoid nested blocks

-(void)openSession {
        [self.loginManager logInWithReadPermissions:@[@"user_photos"]
                                 fromViewController:[self.datasource mediaAccountViewControllerForRequestingOpenSession:self]
                                            handler:[self loginHandler]];
}

-(void(^)(FBSDKLoginManagerLoginResult *result, NSError *error))loginHandler {

    __weak typeof (self) weakSelf = self;

    return ^ (FBSDKLoginManagerLoginResult *result, NSError *error) {

        __strong typeof(weakSelf) strongSelf = weakSelf;

        if (error) {
            [strongSelf.delegate mediaAccount:strongSelf failedOpeningSessionWithError:error];
        } else if (result.isCancelled) {
            [strongSelf.delegate mediaAccountSessionOpeningCancelledByUser:strongSelf];
        } else {
            [strongSelf.delegate mediaAccountDidOpenSession:strongSelf];
        }

        [strongSelf notifyWithCompletion:[strongSelf completionHandler]]
    };
}

-(void)notifyWithCompletion:(void(^)(void))completion {

    [self notify];
    completion();

}

-(void(^)(void))completionHandler {

    return ^ {
        //do something
    };

}

But how do you avoid many nested blocks, which is often the case when you use GCD within a block ?

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

                [self parseLoadsOfData];

                dispatch_async(dispatch_get_main_queue(), ^{

                    [self updateUI];

                });

            });

Are there retain cycles here ?

  • why do you think there will be a retain cycle in any of these cases? – newacct Apr 12 '16 at 07:43
  • passing self into a block. –  Apr 12 '16 at 14:16
  • Nope, there is no *cycle*. cycle = A -> B -> A Where is the cycle? – newacct Apr 12 '16 at 18:30
  • the cycle does exist in certain situations. i will explain with an example. if 'self' was a view controller and the view controller was dismissed by it's parent, I would expect that view controller to be deallocated, if nothing is holding on to it strongly. If this block is waiting on a queue holding onto self strongly, then the view controller will still be in memory. –  Apr 12 '16 at 20:29
  • this is a more clear explanation maybe. hope that helps. http://stackoverflow.com/a/20032131/1951992 –  Apr 12 '16 at 20:32
  • i have answered this question, with an example that might help you understand http://stackoverflow.com/a/36583600/1951992 –  Apr 12 '16 at 20:39
  • But that is still not a "cycle". The view controller is not strongly referencing the block or the queue. – newacct Apr 13 '16 at 17:45
  • If you post that as an answer, I will accept it. –  Apr 14 '16 at 18:46

1 Answers1

0
__weak typeof(self) *weakSelfOuter = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    __strong typeof(self) *strongInnerSelf1 = weakSelfOuter;
    [strongInnerSelf1 parseLoadsOfData];
    __weak typeof(self) *weakInnerSelf = strongInnerSelf1;
    dispatch_async(dispatch_get_main_queue(), ^{
        __strong typeof(self) *strongInnerSelf2 = weakInnerSelf;
        [strongInnerSelf2 updateUI];
    });
});
  • A couple of comments about this: - once you recapture `weakSelfOuter` into `strongInnerSelf1`, it's generally good practice to check `strongInnerSelf1` for nil in case you actually need to dereference an ivar on self directly (not strictly necessary in this case) - you also don't need to re-weaken `strongInnerSelf1` to `weakInnerSelf`; in the inner dispatch back to main, you can just recapture `weakSelfOuter`. – fullofsquirrels Apr 08 '16 at 22:06
  • you are referencing 'self' within a block twice here. __weak typeof(self) and __strong typeof (self) –  Apr 09 '16 at 23:20