简体   繁体   中英

Removing a view from it's superview after animation repositions other views

My app simulates a playing card game. I have a view called gridView in my controller, which contains 16 card views. The card views are already positioned inside the grid view (it's the green one) without any layout constraint:

在此处输入图片说明

Now in some moment of the game I need to animate two card views, displacing them outside the screen bounds, and after the animation is completed, I need to remove them from it's superview (the grid view). But I need to do this not simultaneously, but one view per time, so I use an animation that when finishes it triggers the other one.

I use two arrays: cardViews contains all the card views inside the grid view, but not the ones that need to be removed with an animation, those are contained in matchedCardViews . So I've written this method:

- (void) animateMatchedCardViews {
    if(self.matchedCardViews.count) {
        UIView* view= self.matchedCardViews.firstObject;
        [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
            view.frame= aFrameOutOfScreenBounds;  // I checked out: the frame is computed
                                                  // correctly, converted in grid view's
                                                  // coordinates
        } completion:^(BOOL finished) {
            [view removeFromSuperview];
            [self.matchedCardViews removeObject:view];
            // I recursively call the method to remove the other card
            // in self.matchedCardViews. 
            [self animateMatchedCardViews];
        }];
    }
}

But removing the view from it's superview messes up everything: the first animation goes well and I see the view slowly going out of the screen, but the second animation is totally wrong: all other views I don't know why are layout'd again, in wrong positions, and the second card view that should animate moves not to a point outside the screen, but inside the grid view. The view in a red circle is the one that moved to a wrong position:

在此处输入图片说明

PS: If I don't call the line [view removeFromSuperview] all fixes, but I need to remove it from the superview.

Try this,

- (void) animateMatchedCardViews {
    if(self.matchedCardViews.count) {
        UIView* view= self.matchedCardViews.firstObject;
        [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
            view.frame= aFrameOutOfScreenBounds;  // I checked out: the frame is computed
                                              // correctly, converted in grid view's
                                              // coordinates
        } completion:^(BOOL finished) {
           if (finished) {
               [view removeFromSuperview];
               [self.matchedCardViews removeObject:view];
               // I recursively call the method to remove the other card
               // in self.matchedCardViews. 
               [self animateMatchedCardViews];
           }

        }];
    }
}

It seems like xcode wants to automatically add constraints to views for which no constraint is specified, if I use autolayout:

在此处输入图片说明

Probably it does so to resolve the ambiguity, but in my case there isn't any ambiguity because I manually position the views inside the grid view.

The solution I've found is to subclass UIView and to override addConstraint: and addConstraints: , without calling the superclass implementation so that the constraints aren't really added. This works perfectly without any crash.

- (void) addConstraint:(NSLayoutConstraint *)constraint {
}

- (void) addConstraints:(NSArray *)constraints {
}

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