警告从后台线程调用UIKit
iOS的UIKit不是线程安全的,让我们称之为众所周知的事实。 我知道这个规则,我很小心,但我仍然很沮丧 - 不时地发生的崩溃已经足够远离从违规的背景调用到UIKit,从而使问题跟踪不到joyeus的体验。
这个问题似乎很容易解决 - UIKit类/方法在从后台线程调用时会发出警告,至少作为调试功能。 据我所知,iOS不提供任何此类功能。 当然,人们可以通过在这种调用之前进行某种形式的断言来手动达到相同的效果,但是这种解决方案并不是最优雅的,并且与原始问题一样具有相同的弱点,即程序员容易发生健忘。
有没有人有更优雅的解决方案? 你如何在你的项目中处理这个问题?
(注意:这个问题是相关的,但不是很明确,其中一个是想知道的)
更新 :安德鲁的答案是我当时正在寻找的解决方案,但请注意,至少从Xcode 9开始,现在由xcode / ios提供。 例如,添加下面的代码:
DispatchQueue.global().async {
print(self.view.frame)
}
对于UIView的viewDidLoad方法在Xcode中产生内联运行时警告UIView.frame必须仅在主线程中使用,并且将消息输出到控制台:主线程检查器:在后台线程上调用UI API: - [UIView帧]
此代码(仅添加到项目并在没有ARC的情况下编译此文件)会导致主线程之外的UIKit访问断言:https://gist.github.com/steipete/5664345
我刚刚用它来拾取我刚刚拾取的一些代码中的许多UIKit /主线程问题。
我尝试不引入多线程,除非我先尝试了单线程的方法,但这取决于您正在尝试解决的问题。
即使多线程是唯一的选择,我通常会避免长时间运行的后台操作或执行多个不相关任务的操作。
只是我的观点。
编辑
显示加载微调器时在主线程上执行工作的示例:
MBProgressHUD *hud = [MBProgressHUD customProgressHUDInView:view dim:dim];
[hud show:NO];
//Queue it so the ui has time to show the loading screen before the op starts
NSBlockOperation *blockOp = [NSBlockOperation blockOperationWithBlock:block];
NSBlockOperation *finOp = [NSBlockOperation blockOperationWithBlock:^{
[MBProgressHUD hideAllHUDsForView:view animated:NO];
}];
[finOp addDependency:blockOp];
[[NSOperationQueue mainQueue] addOperations:@[blockOp, finOp] waitUntilFinished:NO];
就个人而言,我打开盒子到多线程方法,我开始在performSelectorOnMainThread:
包装所有基于接口的调用performSelectorOnMainThread:
这样就永远不会有问题。 如果我们已经将其调用到main函数中,那么调用不应该导致任何明显的减速,但是如果从后台线程中调用它,我可以轻松地知道它的安全性。
上一篇: Warn on calls to UIKit from background threads
下一篇: DLL Code injection to third party process using QueueUserAPC