简体   繁体   English

动画进入后台后使App崩溃

[英]Animations crash App after going into background

After looking for some feedback on how to clean up animations once they've finished I implemented the following; 寻找有关动画完成后如何清理的反馈后,我实现了以下内容:

- (void)onAnimationComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
    UIImageView *AnimationImageEnd = context;
    [AnimationImageEnd removeFromSuperview];
    [AnimationImageEnd release];
}

and to set them off (I've removed some of the frames and rotation calcs); 并将其关闭(我已经删除了一些框架和旋转计算);

UIImageView * AnimationImageStart = [[UIImageView alloc] initWithImage: AnimationImage];
[self addSubview:AnimationImageStart];
[UIView beginAnimations:nil context:AnimationImageStart];
[UIView setAnimationDuration:iSpeed];
AnimationImageStart.transform = transform;
[UIView setAnimationDidStopSelector:@selector(onAnimationComplete:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView commitAnimations];

This seems to be working fine and cleaning up all used memory once the animation completes. 动画完成后,这似乎可以正常工作并清理所有使用的内存。

Since implementing this approach I have now got issues with re-opening the App once it goes into the background if an animation had started before hand. 自从实施这种方法以来,如果动画是事先开始播放的,那么一旦进入后台,我现在就遇到了重新打开该应用程序的问题。 The App is now crashing with the following error; 该应用程序现在因以下错误而崩溃;

*** -[UIImage _isDecompressing]: message sent to deallocated instance 0x21083ad0

I've had a tinker and it appears to be all down to the release used. 我已经做了一点修补,似乎完全取决于所使用的发行版。 If I remove the [AnimationImageEnd release]; 如果删除[AnimationImageEnd版本]; the crashes stop (but it obviously starts some memory leaks off..). 崩溃停止了(但显然它开始引起一些内存泄漏。)。

Is there something simple I am misunderstanding about the Animations and the App entering / re-opening from the background? 关于动画和从后台进入/重新打开应用程序,我是否容易误解?

My guess is that iOS is automatically cleaning up any animations in progress once it enters the background and automatically fires the release to each. 我的猜测是,iOS进入后台后会自动清理正在进行的所有动画,并自动将其释放给每个动画。 If this is the case, should I just simply expect them to have been cleaned up and hold a flag within the applicationDidBecomeActive to bypass the release? 如果是这种情况,我是否仅希望它们已被清理并在applicationDidBecomeActive中保留一个标志来绕过发行版?


Edit 1 I've read that the finished flag on onAnimationComplete will let me know if the animation completed it's full animation or not. 编辑1我已经阅读到onAnimationComplete上的完成标志将让我知道动画是否完成了它的完整动画。 Is it enough to just trust that if it did not finish it has already been cleaned up (removed from superview and released)? 仅仅相信它如果还没有完成就已经被清理(从超级视图中删除并发布)就足够了吗?


Edit 2 编辑2

As per David's response below I have updated this to a block; 根据下面David的回复,我将其更新为一个大块。

[UIView animateWithDuration:5.0f
                          delay:0.0f
                        options:0
                     animations:^{

                         imgStart.frame = CGRectMake( 0,  0, 10.0f, 10.0f);

                     }
                 completion:^(BOOL finished){

                     [imgStart removeFromSuperview];

                     //This still crashes the App as soon as the App returns from being in the background
                     [imgStart release];

                 }];

The same behaviour as detailed above is still present. 仍然存在与上述相同的行为。 As per Edit 1, is it enough to just assume that whenever the finished BOOL is NO, it has already been cleaned up (removed from superview + released)? 根据编辑1,仅假设已完成的BOOL为否,是否已经将其清除(从superview +释放中移除)就足够了吗?


Any information is greatly appreciated. 任何信息都将不胜感激。

Ralph 拉尔夫

First, please don't use an initial capital letter for an object - reserve those for classes (it makes reading code much harder for most of us). 首先,请不要对对象使用大写字母-将其保留为类(对于我们大多数人来说,阅读代码会更加困难)。

Generally it's bad practice to release objects in callbacks. 通常,在回调中释放对象是一种不好的做法。 Use a dispatch block to the main queue to release the object or a performSelectorOnMainthread:, and see if that helps. 使用分派块到主队列以释放对象或performSelectorOnMainthread:,看看是否有帮助。

EDIT: didn't mean to imply you needed a complete block. 编辑:并不意味着您需要一个完整的块。 Reading the docs again shows no indication of retain change if the animation does not complete. 如果动画没有完成,再次阅读文档不会显示保留更改的迹象。 Since you have a release in your code, you are not using ARC. 由于您的代码中包含发行版,因此您没有使用ARC。

Non-ARC: so imgStart is alloc/inited, no autorelease, so its retain count is 1. You add it to the subview, its now two. 非ARC:因此imgStart是alloc / inited,没有自动释放,因此其保留计数为1。将其添加到子视图中,现在是两个。 You (or the system) removes it from the subview, its now 1. The final release makes it 0 (I'm ignoring the retain/release by the block itself). 您(或系统)将其从子视图中删除,现在为1。最终版本将其设置为0(我忽略了块本身的保留/释放)。 I just cannot see how the system could release it, as its not really anywhere it can be seen (its not an ivar, so viewDidUnload cannot release it). 我只是看不到系统如何释放它,因为它实际上不在可以看到的任何地方(它不是ivar,因此viewDidUnload无法释放它)。 Right now this is a mystery. 现在这是一个谜。

Suppose you converted to ARC: imgStart is released at the start of the animation, two things retain it, the subview array and the block. 假设您已转换为ARC:imgStart在动画开始时发布,保留了两个内容,即子视图数组和块。 When its removed from the subview array (by whoever), retain count goes down by 1, and when the block completes it will release it as well, causing the retain count to go to 0 so it will be released. 当将其从子视图数组中移除(由任何人)时,保留计数将减少1,并且在块完成时也会将其释放,从而导致保留计数变为0从而将其释放。

If nothing above rings a bell or helps, you can at least try and find when/where that object is getting dealloced. 如果上面没有任何提示或帮助,您至少可以尝试查找何时/何处释放该对象。 Create a UIImageView subclass in your .m file: 在您的.m文件中创建UIImageView子类:

@implementation MyIV : UIIMageView
@end
@interface MyIV

- (void)dealloc
{
  [super dealloc];
  NSLog(@"MYIV DEALLOC!!!!");    
}
@end

Put a breakpoint on the log message, and you can see exactly where its getting dealloc'd. 在日志消息上放置一个断点,您可以确切地看到其被取消分配的位置。 I've found this so helpful in the past I created an ARC class to do this even for class clusters on github, called Tracker . 过去,我发现这很有用,因此我创建了一个ARC类,甚至对github上的类集群Tracker也可以做到这一点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM