Search code examples
iosobjective-cuiviewretaincountretain-cycle

Sending removeFromSuperview to self didn't release itself in my scenario


I have a parent UIView and an UITextView as one of the subviews. And I created a button to dismiss the parent UIView like this:

-(void)cancelButtonPressed:(UIButton *)sender
{
    [UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    self.frame = CGRectZero;
    } completion:^(BOOL finished) {
        if (finished) {
            [self removeFromSuperview];
        }
    }];
}

I can tell that the parent UIView didn't get released because if I typed some text into the UITextView and dismissed it, when I opened the UIView again, instead of a blank UITextView, the SAME text is in it again.

I checked the Leaks tool but I didn't see any leaking. So I'm guessing if I have some kind of retain cycle or what.

UPDATE:I have another object (which is the AppDelegate) who is holding the UIView's instance: _myView as a global variable like this:

_myView = [[MyView alloc] init];

_myView.nameLabel.text = _user.screen_name;
[_window addSubview:_myView];

[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
    _myView.frame = CGRectZero;
} completion:nil];

But in order to avoid retain cycle, should I create a weak self like this: __weak MyView *weakSelf and in the animation block do this: [weakSelf removeFromSuperview]?


Solution

  • I've also tried calling removeFromSuperview on the view itself, and it doesn't result in the view being released.

    If you want to release the view, then go with an approach that uses a delegate. That way, you will be able to call removeFromSuperview on the view, once the animation is complete, and set it to nil. This has worked for me in the past.

    So, you can add a method to the view class that you want to animate closed, where you will do the animation. Set your view controller as a delegate to your view, and call some method on the delegate, from the completion block of that animation.

    You can create your own protocol for this. If you keep it general enough, and focus only on animation callbacks, you can reuse the protocol in all your view controllers.