ios - Swift 线程安全计数器变量?用于跟踪何时删除网络事件指示器

标签 ios swift thread-safety

快速解释我的场景:

我有一个 iOS 应用程序,可以使用不同的线程同时执行大量网络调用。在我的 iOS 应用程序中,我想在发生任何网络事件时显示内置(在状态栏上)网络事件指示器。

所以我所做的是在任何网络调用之前启动事件指示器,然后在网络调用出错或成功完成后停止它。

发生的情况(显然)是,一旦一个网络事件操作成功(或错误)完成,它就会删除网络事件指示器,即使我知道正在发生其他网络事件。

所以我的解决方案是创建一个静态变量(因为许多类执行网络事件),它跟踪当前正在执行的网络请求数量(每次启动时增加此静态变量,然后在启动时减少此静态变量)完成(成功或失败),只有当该计数器达到 0 时才会关闭网络事件指示器。

这工作正常,但是现在我们开始讨论我的问题 - 许多不同的线程正在更新这个静态变量,所以我的想法是它需要是线程安全的?

执行此操作的最佳方法是什么 - 我应该将每次调用启动/停止事件指示器(依次递增/递减静态变量)到主线程上,然后保证该变量将被读取/写入也是连续剧吗?

或者我一直在阅读有关使用信号量来告诉线程在变量被锁定时等待,然后在另一个线程完成变量的读取和写入时运行?

抱歉问了这么长的问题,但我想向您介绍一下我目前的情况。

提前致谢

最佳答案

Sviatoslav Yakymiv said ,串行调度队列 可用于同步对计数器的访问,该计数器保持 当前未完成的网络请求数。

可以使用 DispatchQueue.main 来实现此目的,因为 UIApplication.shared.isNetworkActivityIndi​​catorVisible 必须仅是 无论如何都可以在主队列上访问。

最重要的是,计数器和网络指示器的管理 可以封装成一个类 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/

相关文章:

ios - 暴露给外界的同一文件中的 Objective-C 类别

ios - 在 Storyboard中使用 Xib 时,Xib 的 IBOutlets 返回 nil

swift - 在 Swift 单元测试中创建临时文件

php - PHP 是线程安全的吗?

c# - 在另一个线程中调用函数是否安全?

ios - 如何在 iPhone 5 上获取 IMEI

ios - 如何在 Swift 中正确触发/调用 "selector"?

ios - MonoTouch : How to download pdf incrementally as indicated in the Apple slides "Building Newsstand Apps", session 504?

ios - 如何在 UITableView 中按字母顺序对字典数组进行排序和分类,作为 swift 3.0 中的部分

java - Applet Java 控制台 : remove trace message size limit