快速解释我的场景:
我有一个 iOS 应用程序,可以使用不同的线程同时执行大量网络调用。在我的 iOS 应用程序中,我想在发生任何网络事件时显示内置(在状态栏上)网络事件指示器。
所以我所做的是在任何网络调用之前启动事件指示器,然后在网络调用出错或成功完成后停止它。
发生的情况(显然)是,一旦一个网络事件操作成功(或错误)完成,它就会删除网络事件指示器,即使我知道正在发生其他网络事件。
所以我的解决方案是创建一个静态变量(因为许多类执行网络事件),它跟踪当前正在执行的网络请求数量(每次启动时增加此静态变量,然后在启动时减少此静态变量)完成(成功或失败),只有当该计数器达到 0 时才会关闭网络事件指示器。
这工作正常,但是现在我们开始讨论我的问题 - 许多不同的线程正在更新这个静态变量,所以我的想法是它需要是线程安全的?
执行此操作的最佳方法是什么 - 我应该将每次调用启动/停止事件指示器(依次递增/递减静态变量)到主线程上,然后保证该变量将被读取/写入也是连续剧吗?
或者我一直在阅读有关使用信号量来告诉线程在变量被锁定时等待,然后在另一个线程完成变量的读取和写入时运行?
抱歉问了这么长的问题,但我想向您介绍一下我目前的情况。
提前致谢
最佳答案
如Sviatoslav Yakymiv said ,串行调度队列 可用于同步对计数器的访问,该计数器保持 当前未完成的网络请求数。
可以使用 DispatchQueue.main
来实现此目的,因为 UIApplication.shared.isNetworkActivityIndicatorVisible
必须仅是
无论如何都可以在主队列上访问。
最重要的是,计数器和网络指示器的管理 可以封装成一个类 RAII类似方式:
final public class NetworkActivity {
private static var count = 0
public init() {
DispatchQueue.main.async {
if NetworkActivity.count == 0 {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
NetworkActivity.count += 1
}
}
deinit {
DispatchQueue.main.async {
NetworkActivity.count -= 1
if NetworkActivity.count == 0 {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
}
}
}
}
创建一个NetworkActivity
实例会增加全局计数器,
第一个实例使网络指示器可见。
摧毁物体会减少计数器,指标为
当最后一个实例被销毁时隐藏。
使用示例:
let request = URLRequest(...)
var activity: NetworkActivity? = NetworkActivity()
_ = activity // To suppress a "variable was written to, but never read" warning
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
activity = nil
// ...
}
task.resume()
关于ios - Swift 线程安全计数器变量?用于跟踪何时删除网络事件指示器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44864480/