UIDynamicAnimator with layoutSubviews laggy

233 Views Asked by At

I try to implement side bar menu. I already have done it with standard UIView animations, but now i want to add some feelings to it. I decided to use UIViewDynamics. I noticed that, after main view frame changed, it is necessary to recreate UIViewAnimator and all behaviors.

I usually use layoutSubviews view's method. But in that case, my controller inherit UINavigationController and i couldn't override its view, so i worked with controller life cycle methods.

To avoid unexpected result, first i remove all animator behaviors in viewWillLayoutSubviews method. After that, at end of viewDidLayoutSubviews I create an animator and behaviors (gravity, item, push, collision).

That works fine, but when layoutSubviews triggered, it is some lags (looks like low fps).

Some code:

- (void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];
    if (_animator) {
        [_animator removeAllBehaviors];
        _animator = nil;
    }
}

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];

    [self configSubviewFrames];
    [self configAnimator];
}

- (void)configSubviewFrames
{
    CGFloat offset = [UIApplication sharedApplication].isStatusBarHidden ? 0 : _statusBarHeight;
    CGRect  drawerFrame, protectionFrame, unusedFrame;

    CGRectDivide(self.view.frame, &drawerFrame, &unusedFrame, _drawerWidth, CGRectMinXEdge);

    protectionFrame= self.view.frame;

    if (!_isMenuShown) {
        drawerFrame.origin.x -= _drawerWidth;
    }
    drawerFrame.origin.y += offset;
    drawerFrame.size.height -= offset;
    protectionFrame.origin.y += offset;
    protectionFrame.size.height -= offset;

    _drawerView.frame      = drawerFrame;
    _protectionView.frame  = protectionFrame;
}

- (void)configAnimator
{
    _animator           = [[UIDynamicAnimator alloc] initWithReferenceView:self.view];
    _collisionBehavior  = [[UICollisionBehavior alloc] initWithItems:@[_drawerView]];
    _itemBehavior       = [[UIDynamicItemBehavior alloc] initWithItems:@[_drawerView]];
    _gravityBehavior    = [[UIGravityBehavior alloc] initWithItems:@[_drawerView]];
    _pushBehavior       = [[UIPushBehavior alloc] initWithItems:@[_drawerView] mode:UIPushBehaviorModeInstantaneous];

    _itemBehavior.allowsRotation            = NO;
    _itemBehavior.elasticity                = kDrawerElacity;
    _gravityBehavior.gravityDirection       = CGVectorMake(_isMenuShown ? 1.0f : -1.0f, 0.0f);
    _pushBehavior.magnitude                 = 0.0f;
    _pushBehavior.angle                     = 0.0f;
    _collisionBehavior.collisionDelegate    = self;
    [_collisionBehavior setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(0, - _drawerWidth, 0, self.view.frame.size.width - _drawerWidth)];

    [self addInititalBihaviors];
}


- (void)addInititalBihaviors
{
    [_animator addBehavior:_collisionBehavior];
    [_animator addBehavior:_pushBehavior];
    [_animator addBehavior:_gravityBehavior];
    [_animator addBehavior:_itemBehavior];
}

Hope you will help and feel free to ask any related questions. Thanks you.

App consume 9-12 % cpu on screen rotate.

P.S.: I already tried to move animator and behaviors creation into separated thread, but:

  1. Working with view in background thread - bad idea
  2. It just didn't help
0

There are 0 best solutions below