Ios 从后台线程调用UIKit时发出警告

Ios 从后台线程调用UIKit时发出警告,ios,uikit,Ios,Uikit,iOS的UIKit不是线程安全的,让我们称之为众所周知的事实。我知道规则,我很小心,但我还是会被咬——而且偶尔会导致崩溃,这与对UIKit的令人不快的背景调用相去甚远,从而使跟踪问题的体验不如joyeus 这个问题似乎很容易解决——让UIKit类/方法在从后台线程调用时发出警告,至少作为调试功能。据我所知,iOS没有提供任何这样的功能。当然,通过在这些调用之前使用某种形式的断言,可以手动实现相同的效果,但这种解决方案并不是最优雅的,而且还存在与原始问题相同的弱点,即程序员容易健忘 有人有更优雅的

iOS的UIKit不是线程安全的,让我们称之为众所周知的事实。我知道规则,我很小心,但我还是会被咬——而且偶尔会导致崩溃,这与对UIKit的令人不快的背景调用相去甚远,从而使跟踪问题的体验不如joyeus

这个问题似乎很容易解决——让UIKit类/方法在从后台线程调用时发出警告,至少作为调试功能。据我所知,iOS没有提供任何这样的功能。当然,通过在这些调用之前使用某种形式的断言,可以手动实现相同的效果,但这种解决方案并不是最优雅的,而且还存在与原始问题相同的弱点,即程序员容易健忘

有人有更优雅的解决方案吗?你在项目中如何处理这个问题

(注意:是相关的,但不是很明确。人们会感到疑惑)


更新:Andrew的答案是我当时正在寻找的解决方案,但是请注意,至少在Xcode 9中,这是由Xcode/ios提供的。例如,添加以下代码:

DispatchQueue.global().async {
        print(self.view.frame)
    }

对于UIView,viewDidLoad方法在Xcode中内联生成运行时警告UIView.frame只能从主线程使用,并将消息打印到控制台:主线程检查器:在后台线程上调用的UI API:-[UIView frame]

我尝试不引入多线程,除非我先尝试了单线程方法,但这取决于您试图解决的问题

即使多线程是唯一的选择,我通常也会避免长时间运行的后台操作或执行几个不相关任务的操作

只是我的意见

编辑 显示加载微调器时在主线程上执行操作的示例:

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:
中包装所有基于接口的调用,这样就永远不会出现问题。如果我们已经到达主线程,那么这个调用不应该导致任何明显的速度减慢,但是如果它是从后台线程调用的,我可以放心知道它的安全性。

这段代码(只需添加到项目中并编译这个文件而不使用ARC)会在主线程之外对UIKit访问进行断言:


我刚刚用它在我刚学到的一些代码中发现了许多UIKit/主线程问题。

这不再是普遍正确的。例如,这个函数有12个:
在iOS 4和更高版本中,您可以从应用程序的任何线程调用此函数。
我想当您这样看待它时,可能是这样的,但防御性编码是每个开发人员的标准和推荐做法。特别是早期开发人员的多线程处理。如果您不知道某个东西是否是线程安全的,那么应该假定它是不安全的。所以,只要你有信心,就启动主线程,转到背景线程,而不是相反。这似乎不是对所问问题的答案。这是我当时正在寻找的答案。但是请注意,xcode/ios现在提供了此功能,开发人员无需执行任何操作。请参见更新问题中的示例