首先,我的协议看起来像这样:
@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
(=主线程中)的情况下调用代理,一切都会顺利。
为什么会这样?是否允许从异步块调用动画?非常感谢任何帮助。
答案 0 :(得分:3)
您必须始终在主线程上调用UI相关代码。不这样做是被禁止的,并且会导致意想不到的结果(通常是例外)。
调用您的委托方法时,您应该再次使用dispatch_async
dispatch_get_main_queue
,以便委托代码在主线程上运行,您可以更新您的UI。
有关更具体的信息,另请参阅these Apple docs。
答案 1 :(得分:1)
对GUI元素的任何更改,例如动画,大小和内容都应该在主线程上发生,否则会产生奇怪的效果。