11

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

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

4

3 回答 3

24

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

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

[UIView setAnimationsEnabled:YES];

可能这会有所帮助。

于 2014-01-06T11:59:06.640 回答
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使用此代码,您可以通过在函数体上添加符号断点或仅在函数体中粘贴断点来停止应用程序。

要旨

于 2014-10-02T20:18:20.700 回答
1

扩展 Vinay 的解决方案,这就是我所做的:

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

它似乎解决了这个问题。

于 2014-01-13T14:27:13.673 回答