从dispatch_async块调用时,UIView animateWithDuration使app挂起

时间:2015-01-04 15:11:49

标签: ios objective-c multithreading animation uiview

首先,我的协议看起来像这样:

@protocol CryptoDelegate <NSObject>
- (void)cryptoManagerFinishedEncryption;
@end

Theres是一个名为CryptoManager的单身人士,具有以下功能:

- (void)startEncryption:(NSURL *)path withDelegate:(id<CryptoDelegate>)delegate {
   dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // ... some stuff is happening here
        [delegate cryptoManagerFinishedEncryption];
    });
}

然后我有一个自制MultiPopup可以显示面板(必须扩展MultiPopupPanel以存储指向弹出窗口的指针)并使用以下代码在这些面板之间切换:

- (void)switchTo:(MultiPopupPanel*)panel {
    if(self.currentPanel != panel) {
        MultiPopupPanel* oldPanel = self.currentPanel;
        self.currentPanel = panel;
        self.currentPanel.alpha = 0;
        self.currentPanel.hidden = NO;

        if(oldPanel) {
            NSLog(@"Before animation");
            [UIView animateWithDuration:0.2f animations:^{
                oldPanel.alpha = 0;
            } completion:^(BOOL finished) {
                NSLog(@"After animation");
                oldPanel.hidden = YES;
                [UIView animateWithDuration:0.2f animations:^{
                    self.currentPanel.alpha = 1;
                }];
            }];
        } else {
            [UIView animateWithDuration:0.2f animations:^{
                self.currentPanel.alpha = 1;
            }];
        }
    }
}

现在我有一个扩展MultiPopupPanel并实现协议CryptoDelegate的面板。在cryptoManagerFinishedEncryption实现中,我正在调用我的switchTo函数,然后应该切换到另一个面板。

这是应用程序挂起的地方:立即输出消息“Before animation”。然后应用程序挂起15-20秒,然后动画发生,输出“After animation”消息并显示新面板。

只有在我从另一个线程(通过dispatch_async)使用+[UIView animateWithDuration...]时才会发生这种情况。如果我在没有dispatch_async(=主线程中)的情况下调用代理,一切都会顺利。

为什么会这样?是否允许从异步块调用动画?非常感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

您必须始终在主线程上调用UI相关代码。不这样做是被禁止的,并且会导致意想不到的结果(通常是例外)。

调用您的委托方法时,您应该再次使用dispatch_async dispatch_get_main_queue,以便委托代码在主线程上运行,您可以更新您的UI。

有关更具体的信息,另请参阅these Apple docs

答案 1 :(得分:1)

对GUI元素的任何更改,例如动画,大小和内容都应该在主线程上发生,否则会产生奇怪的效果。