简体   繁体   中英

UICollisionBehavior memory leak

I've run into what I believe is a bug with UICollisionBehavior in UIKit . Adding them to an array of UIViews leads to a memory leak. I put together a simple demo project that creates 10 animations of a group of views falling with gravity applied, and a collision with the enclosing view's bounds. (Code below.) The Leaks template in Instruments reports nine 64-byte leak for each run.

- (void)doAnimation
{
    self.animateButton.enabled = NO;

    CGFloat left = 12.0f;
    NSMutableArray *items = [NSMutableArray new];

    // set up an array of views and add them to the superview
    while (left < self.view.bounds.size.width - 12.0f) {
        UIView *view = [[UIView alloc] initWithFrame:CGRectMake(left, 70, 32, 32)];
        left += 34.0f;
        [self.view addSubview:view];
        view.backgroundColor = [UIColor grayColor];
        [items addObject:view];
    }

    // create a gravityBehavior and initialize with views array
    UIGravityBehavior *gravity = [[UIGravityBehavior alloc] initWithItems:items];
    [self.animator addBehavior:gravity];

    // create a collisionBehavior and initialize with views array
    UICollisionBehavior *collision = [[UICollisionBehavior alloc] initWithItems:items];
    collision.translatesReferenceBoundsIntoBoundary = YES;
    [self.animator addBehavior:collision];
}

// UIDynamicAnimatorDelegate method that's called when collision animation is complete
- (void)dynamicAnimatorDidPause:(UIDynamicAnimator *)animator
{
    // get a collision behavior in order to access its items for loop below
    UICollisionBehavior *behavior;
    for (UIDynamicBehavior *oneBehavior in animator.behaviors) {
        if ([oneBehavior isKindOfClass:[UICollisionBehavior class]]) {
            behavior = (UICollisionBehavior *)oneBehavior;
            break;
        }
    }

    // reset the UIDynamicAnimator property's behaviors for next run
    [self.animator removeAllBehaviors];

    self.dropCount++;

    // remove all subviews
    for (UIView *view in behavior.items) {
         [view removeFromSuperview];
    }

    // run the animation again or break
    if (self.dropCount < 10) {
        [self doAnimation];
    } else {
        self.animateButton.enabled = YES;
    }
}

I'd really like to be able to implement collisions in an app I'm working on, but this leak makes it unusable. I have tried saving the collisionBehavior in property and reusing it. That prevents leaking all but one 64-byte chunk of memory, but the collisions no longer work when that's done. Can anyone suggest a workaround that works?

I ran into the same issue but fixed the memory leak by setting the boundaries using UICollisionBehavior's

addBoundaryWithIdentifier

Unfortunately setting boundaries with translatesReferenceBoundsIntoBoundary and setTranslatesReferenceBoundsIntoBoundaryWithInsets caused leaks for me.

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