繁体   English   中英

因此,如何使 DispatchGroup 与 DispatchQueue 一起工作?

[英]How do I make DispatchGroup work consequently with DispatchQueue?

我有两个 ViewController,第一个用于显示新闻,第二个用于选择将在第一个 VC 中显示的新闻源。 这是我用于在 FeedViewController 中获取新闻的代码。

@objc private func fetchData() {
    articles = []
    let dispatchGroup = DispatchGroup()
    for source in MediaSourceManager.shared.getMediaSources(coreDataStack: coreDataStack) {
        if source.isSelected {
            dispatchGroup.enter()
            FeedAPI.shared.getArticles(newsSource: source) { (articles) in
                self.articles += articles
                dispatchGroup.leave()
            }
        }
    }

    dispatchGroup.notify(queue: .main) {
        self.feedTableView.reloadData()
    }
}

在 getArticles 中,它只是一个 URLSession.shared.dataTask 请求。

在 MediaSourceManager 我有

private let concurrentQueue = DispatchQueue(label: "News.mediaQueue", attributes: .concurrent)

private var unsafeSources: [MediaSource] = []

var safeSources: [MediaSource] {
    var mediasCopy: [MediaSource]!
    concurrentQueue.sync {
        mediasCopy = self.unsafeSources
    }

    return mediasCopy
}

func changeSourceIsSelected(at index: Int) {
    concurrentQueue.async(flags: .barrier) { [weak self] in
        guard let self = self else { return }
        self.unsafeSources[index].isSelected = !self.unsafeSources[index].isSelected
        DispatchQueue.main.async { [weak self] in
            self?.postSelectionNotification()
        }
    }
}

postSelectionNotification 中的代码

private func postSelectionNotification() {
    NotificationCenter.default.post(name: .mediaSelectedChanged, object: nil)
}

在 getArticles 中,我将每个文章描述从 html 字符串转换为普通字符串,这似乎是一项繁重的任务。 因此,我遇到了诸如索引超出范围之类的错误和奇怪的行为,例如我删除的来源的文章仍会显示,如果我在 UI 中快速执行所有操作(选择各种媒体源并快速移动到提要屏幕),就会发生这种情况。 我怎样才能解决这个问题?

这不是解决这个问题的最佳方法,但我还是会分享我的方法。 首先,在 FeedViewController 中,添加一个变量 count 来跟踪正在处理的请求数,以及一个 UIActivityIndicator。 确保当您的活动指示器运行时,为 FeedViewController 禁用了 userInteraction。

@objc private func fetchData() {
    articles = []
    let dispatchGroup = DispatchGroup()
    count += 1 // This variable is to keep track of the number of requests being run
    if !activityIndicator.isAnimating { activityIndicator.startAnimating() }
    for source in MediaSourceManager.shared.getMediaSources(coreDataStack: coreDataStack) {
        if source.isSelected {
            dispatchGroup.enter()
            FeedAPI.shared.getArticles(newsSource: source) { (articles) in
                self.articles += articles
                dispatchGroup.leave()
            }
        }
    }

    dispatchGroup.notify(queue: .main) {
        self.count -= 1
        if self.count == 0 {
             self.activityIndicator.stopAnimating()
             self.feedTableView.reloadData()
        }
    }
}

如果我能想到更好的解决方案,我会更新我的答案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM