【问题标题】:Chaining animations and memory management链接动画和内存管理
【发布时间】:2009-09-22 21:16:03
【问题描述】:

有一个问题。我有一个子类 UIView 作为我滚动地面的背景。代码运行得非常好,根据 Instrumentation,我没有泄漏,我创建的仍然存在的对象分配也没有增长。

我发现在我的应用程序中的其他地方,将动画添加到我的子类 UIView 拥有的 UIImageView 似乎会增加我的保留计数并在我完成后删除所有动画将其放回原处。

我的问题是,当您将动画添加到带有键的图层时,我假设如果在后备字典中的该条目位置已经有一个使用过的动画,它会被释放并进入自动释放池?

例如:


- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
    NSString *keyValue = [theAnimation valueForKey:@"name"];
    if ( [keyValue isEqual:@"step1"] && flag ) {
        groundImageView2.layer.position = endPos;

        CABasicAnimation *position = [CABasicAnimation animationWithKeyPath:@"position"];
        position.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        position.toValue = [NSValue valueWithCGPoint:midEndPos];
        position.duration = (kGroundSpeed/3.8);
        position.fillMode = kCAFillModeForwards;
        [position setDelegate:self];
        [position setRemovedOnCompletion:NO];
        [position setValue:@"step2-1" forKey:@"name"];

        [groundImageView2.layer addAnimation:position forKey:@"positionAnimation"]; 

        groundImageView1.layer.position = startPos;
        position = [CABasicAnimation animationWithKeyPath:@"position"];
        position.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        position.toValue = [NSValue valueWithCGPoint:midStartPos];
        position.duration = (kGroundSpeed/3.8);
        position.fillMode = kCAFillModeForwards;
        [position setDelegate:self];
        [position setRemovedOnCompletion:NO];
        [position setValue:@"step2-2" forKey:@"name"];

        [groundImageView1.layer addAnimation:position forKey:@"positionAnimation"]; 
    }
    else if ( [keyValue isEqual:@"step2-2"] && flag ) {
        groundImageView1.layer.position = midStartPos;

        CABasicAnimation *position = [CABasicAnimation animationWithKeyPath:@"position"];
        position.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
        position.toValue = [NSValue valueWithCGPoint:endPos];
        position.duration = 12;
        position.fillMode = kCAFillModeForwards;
        [position setDelegate:self];
        [position setRemovedOnCompletion:NO];
        [position setValue:@"step1" forKey:@"name"];

        [groundImageView1.layer addAnimation:position forKey:@"positionAnimation"]; 
    }
}

这无限地链接动画,正如我所说的那样,它正在运行创建的和活动的对象分配不会改变。我假设每次添加动画时都会释放存在于该关键位置的动画。

只是想知道我是对的。另外,我对 Core Animation 比较陌生。我试图重新使用动画,但有点不耐烦。是否可以重复使用动画?

谢谢! 布莱恩

【问题讨论】:

    标签: iphone memory-management animation


    【解决方案1】:

    如果没有 Apple 的源代码,您的假设很难验证。当您调用addAnimation:forKey: 时,CALayer 会复制动画对象。 API(在文档或其他地方)不能保证当为同一个键添加另一个动画时它会释放一个正在运行的动画。显式调用 removeAnimation:forKey: 比依赖 API 来做你想做的事对你来说要安全得多。

    另外,为什么在上面的代码中将removedOnCompletion 设置为NOCAAnimation 的默认行为是在完成后将自身从层中移除,然后在委托上调用 animationDidStop:finished:。然后,您可以使用相同的键将任何其他动画添加到图层。这不正是你想要做的吗?看来您可能想多了。

    关于您关于重用动画的问题:由于动画对象在添加到CALayer 时会被复制,因此您可以保留对您创建的动画对象的引用,并继续将其添加到任意数量的图层中随心所欲。

    【讨论】:

    • 关于removedOnCompletion,stackoverflow 上的其他答案表明,除非您将此设置为NOfillModekCAFillModeForwards,否则您的动画结果将不会持久。也就是说,从CALayer 中删除CAAnimation 将删除任何属性更改。 Apple 显然希望属性动画是非破坏性的。您可以使用animationDidStop:finished 方法将属性设置为最终状态,但您通常会得到一个图形“blip”,其中 CALayer 恢复到其动画前状态。看起来很可怕。
    • 这基本上是正确的,但有一种更简单的方法。动画不会应用于图层本身。而是创建了一个名为presentationLayer 的副本,并将动画应用于它。此外,由于主运行循环的每次迭代都包含在隐式 CATransaction 中,因此您可以在添加动画之前设置层的最终属性。包括动画在内的所有改动都会一次性提交,而且开头和结尾都不会出现blip。例如:myLayer.position = CGPointMake(100, 100); [myLayer addAnimation:anim forKey:@"position"];
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-10
    • 2016-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多