从后台线程访问 [UIApplication sharedApplication] 可以吗?
Posted
技术标签:
【中文标题】从后台线程访问 [UIApplication sharedApplication] 可以吗?【英文标题】:Is it ok accessing [UIApplication sharedApplication] from background thread? 【发布时间】:2020-02-11 07:35:21 【问题描述】:在处理Objective-C
时,我可能需要在一些后台线程中获取protectedDataAvailable
状态。
- (BOOL) isProtected
BOOL protectedDataAvailable = [[UIApplication sharedApplication] isProtectedDataAvailable];
return protectedDataAvailable;
当我访问[UIApplication sharedApplication]
时,我怀疑代码块应该在主队列中运行。 我该怎么做?
我想改变它,
- (BOOL) isProtected
BOOL protectedDataAvailable = NO;
dispatch_sync(dispatch_get_main_queue(), ^
protectedDataAvailable = [[UIApplication sharedApplication] isProtectedDataAvailable];
);
return protectedDataAvailable;
问题 1:代码是否应该在主队列/UI 线程中运行?
问题 2:如果是,我更改的代码会解决问题吗?还是有更好的方法?
我问这个问题的原因是,即使我同步访问 主队列 上的UIApplication
,当从main thread
调用块时,它也会崩溃。我该如何处理这个问题?
【问题讨论】:
【参考方案1】:问题 1:代码是否应该在主队列/UI 线程中运行?
肯定是的,因为如果您在 Xcode 上使用主线程检查器运行您的应用程序,当从后台线程访问时,调用 UIApplication sharedApplication
会突出显示为问题
问题 2:如果是,我更改的代码会解决问题吗?
除非你从主线程调用isProtected
是的。
或者有没有更好的方法?
我会坚持这样的:
- (BOOL)isProtected
__block BOOL protectedDataAvailable = NO;
if ([NSThread isMainThread])
protectedDataAvailable = [[UIApplication sharedApplication] isProtectedDataAvailable];
else
dispatch_sync(dispatch_get_main_queue(), ^
protectedDataAvailable = [[UIApplication sharedApplication] isProtectedDataAvailable];
);
return protectedDataAvailable;
正如 Alejandro Ivan 在评论中指出的那样,您可以使用简单的dispatch_sync
而不是使用信号量
【讨论】:
为什么将dispatch_async()
与信号量一起使用而不是仅仅使用dispatch_sync()
?可以肯定的是,手动处理信号量很昂贵。我会使用- (BOOL)isProtected __block BOOL protectedDataAvailable = NO; dispatch_sync(dispatch_get_main_queue(), ^ protectedDataAvailable = [[UIApplication sharedApplication] isProtectedDataAvailable]; ); return protectedDataAvailable;
@AlejandroIván 我同意。简单的 dispatch_sync 绝对是一个选项,至少有更少的代码,甚至(我不确定)更少的开销
主要区别在于 GCD 队列不使用锁(因此它们是单线程访问),但信号量确实使用它们(尽管轻量级互斥锁)。这使得信号量与多线程兼容。对于普通的 UI 应用程序,可能不需要信号量。
@AndreyChernukha 如果我使用dispatch_sync
,我只需要删除与信号量相关的行,对吗?如果您更新代码以使用dispatch_sync
,这将很有帮助。以上是关于从后台线程访问 [UIApplication sharedApplication] 可以吗?的主要内容,如果未能解决你的问题,请参考以下文章
主线程检查器:在后台线程上调用的 UI API:-[UIApplication applicationState]
后台运行之[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil]
- (void)applicationWillTerminate:(UIApplication *) 当应用程序从后台移除时应用程序没有调用