在viewDidUnload上停止递归函数

时间:2011-09-20 16:01:03

标签: iphone objective-c cocoa-touch

我有一个连续播放UIView动画的递归函数(如果有更好的方法,请告诉我):

-(void)playAnimationRecursive
{
    [appDelegate commenceFishAnimation];
    [animationView addSubview:appDelegate.fishAnimationImageView];
    animationView.alpha=0.5;

    [NSTimer scheduledTimerWithTimeInterval:14.0 target:self selector:@selector(playAnimationRecursive) userInfo:nil repeats:NO];
}

并且不确定这是否是必要的,但这里是appDelegate beginFishAnimationMethod:

        upperFish=[[UIImageView alloc] initWithImage:upperFishImage];
        bigFish=[[UIImageView alloc] initWithImage:bigFishImage];
        shark=[[UIImageView alloc] initWithImage:sharkImage];
        groupFish=[[UIImageView alloc] initWithImage:groupFishImage];
        fish1=[[UIImageView alloc] initWithImage:fish1Image];
        fishAnimationImageView=[[[UIImageView alloc] init] retain];

        //set the initial position of each fish to be out of frame
        upperFish.frame=CGRectMake(-50, 150, 119/2, 93/2); //moves east
        bigFish.frame=CGRectMake(-280, 340, 251/2, 137/2); //moves east
        shark.frame=CGRectMake(-100, 390, 164/2, 52/2); //moves east
        groupFish.frame=CGRectMake(500, 320, 155/2, 89/2); //moves west
        fish1.frame=CGRectMake(370, 280, 155/2, 89/2); //moves west

        //add fishes to current view
        [fishAnimationImageView addSubview:upperFish];
        [fishAnimationImageView addSubview:bigFish];
        [fishAnimationImageView addSubview:shark];
        [fishAnimationImageView addSubview:groupFish];
        [fishAnimationImageView addSubview:fish1];

        //animate the position of each fish view
        [UIView beginAnimations:nil context:NULL];
        [UIView setAnimationDuration:10.0];
        [UIView setAnimationCurve:UIViewAnimationCurveLinear];
        upperFish.transform=CGAffineTransformMakeTranslation(150, -200);
        bigFish.transform=CGAffineTransformMakeTranslation(600, 0);
        shark.transform=CGAffineTransformMakeTranslation(550, 0);
        groupFish.transform=CGAffineTransformMakeTranslation(-600, 0);
        fish1.transform=CGAffineTransformMakeTranslation(-550, 0);

        [UIView commitAnimations];
        [fishAnimationImageView release];
        [upperFish release];
        [bigFish release];
        [shark release];
        [groupFish release];
        [fish1 release];  
}

所以会发生的是我在BG中播放这个动画的每个视图,所以如果我在视图A上,那么它会调用递归函数并连续播放动画。如果我移动到视图B,那么它也会调用递归函数并连续播放动画。但是,我的内存警告级别为2,我想也许是因为视图A仍在调用递归方法?如果这是原因,那么我将如何在卸载时停止递归方法?或者那不是我的问题吗?

编辑:

现在这是我的代码(动画不循环)

-(void)commenceFishAnimation
{
    UIImageView *newImageView=[[UIImageView alloc] init];
    self.fishAnimationImageView=newImageView;

    upperFish=[[UIImageView alloc] initWithImage:upperFishImage];
    bigFish=[[UIImageView alloc] initWithImage:bigFishImage];
    shark=[[UIImageView alloc] initWithImage:sharkImage];
    groupFish=[[UIImageView alloc] initWithImage:groupFishImage];
    fish1=[[UIImageView alloc] initWithImage:fish1Image];

    //set the initial position of each fish to be out of frame
    upperFish.frame=CGRectMake(-50, 150, 119/2, 93/2); //moves east
    bigFish.frame=CGRectMake(-280, 340, 251/2, 137/2); //moves east
    shark.frame=CGRectMake(-100, 390, 164/2, 52/2); //moves east
    groupFish.frame=CGRectMake(500, 320, 155/2, 89/2); //moves west
    fish1.frame=CGRectMake(370, 280, 155/2, 89/2); //moves west

    //add fishes to current view
    [fishAnimationImageView addSubview:upperFish];
    [fishAnimationImageView addSubview:bigFish];
    [fishAnimationImageView addSubview:shark];
    [fishAnimationImageView addSubview:groupFish];
    [fishAnimationImageView addSubview:fish1];

    //animate the position of each fish view
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:10.0];
    [UIView setAnimationCurve:UIViewAnimationCurveLinear];
    upperFish.transform=CGAffineTransformMakeTranslation(150, -200);
    bigFish.transform=CGAffineTransformMakeTranslation(600, 0);
    shark.transform=CGAffineTransformMakeTranslation(550, 0);
    groupFish.transform=CGAffineTransformMakeTranslation(-600, 0);
    fish1.transform=CGAffineTransformMakeTranslation(-550, 0);

    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(commenceFishAnimation)];
    [UIView commitAnimations]; 

    [fishAnimationImageView release];
    [upperFish release];
    [bigFish release];
    [shark release];
    [groupFish release];
    [fish1 release];
    //[newImageView release]; //if I release it, then my animation doesn't play for some reason
}

然后在viewDidLoad方法的其他一些类中,我这样做:

[appDelegate commenceFishAnimation];
[animationView addSubview:appDelegate.fishAnimationImageView];

但动画只播放一次。

2 个答案:

答案 0 :(得分:3)

这不是链接动画的最佳方式,而是使用它:

    [UIView setAnimationDidStopSelector:@selector(playAnimation)];

这将在无限循环中链接您的动画。

但请注意,在您的方法playAnimationRecursive中,您每14秒添加一次子视图并安排NSTimer而不释放它们。这是一个非常糟糕的主意。

总结:忘记递归并使用上面的方法。

编辑:我忘了提到你必须分配动画的代表:

[UIView setAnimationDelegate:self];  //self or whatever implements playAnimation selector

答案 1 :(得分:1)

我看到一些红色标记表明你对目标C中的引用计数没有很好的理解。

[[[UIImageView alloc] init] retain];

永远不要那样做。 alloc已经为您提供了1的引用计数。您也不需要保留它。

fishAnimationImageView=[[[UIImageView alloc] init] retain];

哦,哦,fishAnimationImageView引用的上一个对象发生了什么?它仍然保留,但没有人提及它。泄漏!

[fishAnimationImageView release];

技术上正确,因为您之前将其保留了两次,但通常不应该释放该对象,因为它(我假设)是您的app委托的实例变量。

这是你应该做的。

UIImageView *newFishAnimationImageView = [[UIImageView alloc] init];
// retain count = 1
self.fishAnimationImageView = newFishAnimationView;
// retain count = 2
// old value retain count = 0
// assuming a typical property declaration as retain, and setter made by @synthesize
[newFishAnimationView release];
// retain count = 1; not owned locally, but owned by your app delegate

通过属性引用事物通常可以获得正确的引用计数行为。遵循这一点,以及释放你分配的任何东西的规则,并且在很多情况下你会出错。

您应该查看有关引用计数的文档。

另外,试试产品>在XCode中配置文件,然后选择Leaks。它可以告诉您是否有内存泄漏以及它们的位置。