iosautolayoutuicollisionbehavior

CollisionBehaviour do not working with autolayout


I am trying to implement collisions between two views.

firstView is view with textfields. If some textfield became firstRecognizer and keyboard frame overlap firstView. It moves up and if firstView collides with secondView, it should push it up too. But this does not happen. Instead firstView moves up until collides with secondView and then puts back on old place.

Here code, which I use:

- (void) keyboardChangeValueWithFrame:(CGRect)keyboardFrame isOpening:(BOOL)isOpening isClosing:(BOOL)isClosing {
    CGFloat animTime = .3f;
    if (isOpening && !isClosing) {
        CGRect authFillerViewFrame = self.regFillerView.frame;
        CGFloat rectDif = keyboardFrame.origin.y - authFillerViewFrame.origin.y - authFillerViewFrame.size.height;
        if ([_animator.behaviors containsObject:_collision]) {
            [_animator removeBehavior:_collision];
        }
        if (rectDif < 0) {
            [self.view layoutIfNeeded];
            self.regFillerViewHorizCenterConst.constant = rectDif;
            [self.logoView layoutIfNeeded];
            [UIView animateWithDuration:animTime animations:^{
                _collision = [[UICollisionBehavior alloc] initWithItems:@[self.regFillerView, self.logoView]];
                _collision.translatesReferenceBoundsIntoBoundary = NO;
                _collision.collisionDelegate = self;
                _collision.collisionMode = UICollisionBehaviorModeItems;
                [_animator addBehavior:_collision];
                _collision.action = ^{

                };
                [self.view layoutIfNeeded];
            } completion:^(BOOL finished) {
                if (finished) {
                    //
                }
            }];
        }
    } else if (!isOpening && isClosing) {
        [self.view layoutIfNeeded];
        self.regFillerViewHorizCenterConst.constant = 0.f;
        [UIView animateWithDuration:animTime animations:^{
            [self.view layoutIfNeeded];
        } completion:^(BOOL finished) {
            //
        }];
    }
}

Could somebody tell my mistake? Or, may be somebody know better solution?


Solution

  • I found solution. My mistake was to add collision behaviour to animator before calling layoutIfNeeded. Now I call layoutIfNeeded before adding collision behaviour and it works well.

    [UIView animateWithDuration:animTime animations:^{
                    _collision = [[UICollisionBehavior alloc] initWithItems:@[self.regFillerView, self.logoView]];
                    [self.view layoutIfNeeded];
                    _collision.translatesReferenceBoundsIntoBoundary = NO;
                    _collision.collisionDelegate = self;
                    _collision.collisionMode = UICollisionBehaviorModeItems;
                    [_animator addBehavior:_collision];
                    _collision.action = ^{
    
                    };
                } completion:^(BOOL finished) {
                    if (finished) {
                        //
                    }
                }];