2013-10-16 48 views
11

我看到我的应用程序中的所有ios动画都停止工作。它在iOS7中非常频繁地发生。iOS动画在我的iOS7应用程序中停止工作

嘿,我有一个应用程序,它支持iOS 5,6和7.我最近看到所有的iOS动画在iOS7的应用程序停止工作?

+0

我不知道它背后的原因,但我有完全相同的问题,当我删除它解决了的tableView:willDisplayCell:forRowAtIndexPath:方法,它用来调用大量performSelectorInBackground的显示图像。这可能有助于解决问题,也可能会提供一些提示。 – Mohammad

+0

我确实发现了。当你在后台线程中做UIKit的东西时会发生这种情况。这里是它解释所有事情的链接。 http://stackoverflow.com/questions/18281097/uiviewcontroller-animations-stop-working – user1010819

回答

24

在IOS 7中,当后台线程执行一些主要方法操作时,动画将被禁用。

所以为此,你需要重新启用状(一种解决方法)动画

[UIView setAnimationsEnabled:YES]; 

可能这可以帮助。

+3

我认为它是正确的,虽然这是一个工作。后台线程中不应执行主要的方法操作。 – user1010819

+2

我同意这只是一个解决办法。 –

1

扩展维奈的解决方案,这就是我做的:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      //make calculations 
      dispatch_async(dispatch_get_main_queue(), 
          ^{ 
           [UIView setAnimationsEnabled:YES]; 
          });   
}); 

这似乎解决问题。

+0

这是我期待的最差的答案:D – l0gg3r

+0

它不是完美的,但它的工作 –

+0

什么是外部调度异步?你不能把它删除吗? – AntiMoron

16

我最近遇到了这个问题,我在后台线程上进行了大小计算。通过swizzling setAnimationsEnabled:我发现只有时间我禁用后台线程动画是在-[UIImageView setImage:]

因为这个观点从来没有显示,也没有要求我的计算用图像的变化,我可以在主线程调用附上这个测试:

if ([NSThread isMainThread]) { 
    self.answerImageView.image = [UIImage imageNamed:imgName]; 
} 

值得一提的,我不打这个问题在初始视图实例化,因为我已经在主线程中加载我的模板视图,以避免Xib加载问题。

其他问题可能会更复杂,但您应该能够提出类似的解决方法。这是我用来检测动画背景禁用的类别。

#import <UIKit/UIKit.h> 
#import <JRSwizzle/JRSwizzle.h> 

#ifdef DEBUG 

@implementation UIView (BadBackgroundBehavior) 

+ (void)load 
{ 
    NSError *error = nil; 
    if (![self jr_swizzleClassMethod:@selector(setAnimationsEnabled:) withClassMethod:@selector(SE_setAnimationsEnabled:) error:&error]) { 
     NSLog(@"Error! %@", error); 
    } 
} 

+ (void)SE_setAnimationsEnabled:(BOOL)enabled 
{ 
    NSAssert([NSThread isMainThread], @"This method is not thread safe. Look at the backtrace and decide if you really need to be doing this here."); 
    [self SE_setAnimationsEnabled:enabled]; 
} 

@end 

#endif 

更新

原来显示的媒体元素(rdar:// 20314684)时UIWebView实际上使不安全的调用setAnimationsEnabled:。如果你的应用程序允许任意的Web内容,这使得上面的方法非常痛苦,所以总是处于活动状态。

#import <UIKit/UIKit.h> 
#import <objc/runtime.h> 

#ifdef DEBUG 

void SEViewAlertForUnsafeBackgroundCalls() { 
    NSLog(@"----------------------------------------------------------------------------------"); 
    NSLog(@"Background call to setAnimationsEnabled: detected. This method is not thread safe."); 
    NSLog(@"Set a breakpoint at SEUIViewDidSetAnimationsOffMainThread to inspect this call."); 
    NSLog(@"----------------------------------------------------------------------------------"); 
} 

@implementation UIView (BadBackgroundBehavior) 

+ (void)load 
{ 
    method_exchangeImplementations(class_getInstanceMethod(object_getClass(self), @selector(setAnimationsEnabled:)), 
            class_getInstanceMethod(object_getClass(self), @selector(SE_setAnimationsEnabled:))); 
} 

+ (void)SE_setAnimationsEnabled:(BOOL)enabled 
{ 
    if (![NSThread isMainThread]) { 
     SEViewAlertForUnsafeBackgroundCalls(); 
    } 
    [self SE_setAnimationsEnabled:enabled]; 
} 

@end 

#endif 

有了这个代码,您可以通过添加一个象征性的断点SEViewAlertForUnsafeBackgroundCalls或只是坚持停止你的应用程序:相反,我使用下面的方法,因为它让我打开断点和关闭,并继续失败后开始函数体中的断点。

Gist

+0

这个答案很奇妙。每当这个断言被抛出时,你会在你的源代码中看到你已经搞砸了,并试图做一些不在主线程中的东西。 –

+0

我遇到了这种行为,因为webview不断对setAnimationsEnabled进行不安全的调用:并且遇到了与其他视图动画相关的竞争条件。 有没有办法解决这个webview废话?采用WKWebView不是一种选择,因为webview被封装在第三方类中。 会永久地搅拌setAnimationsEnabled:强迫它在主要运行太危险? – ArkReversed