【问题标题】:iOS - SwiftUI - Navigate to the next screen AFTER async actions performediOS - SwiftUI - 执行异步操作后导航到下一个屏幕
【发布时间】:2020-09-26 21:57:16
【问题描述】:

我对 SwiftUI 以及 DispatchGroups 和 DispatchQueues 还是很陌生。 我想创建一个处理一些服务器请求的按钮,然后将返回的数据与 CoreML 模型一起使用来预测一些分数。一旦预测得分,应用就可以导航到下一个屏幕

这是在移动到下一个屏幕之前需要完成的操作序列


// exemple of sequence of actions
let group = DispatchGroup()
group.enter()
DispatchQueue.main.async {
    self.name = self.names[self.selectedCompanyIndex]
    self.fetchTweets(company: self.arobases[self.selectedCompanyIndex])
    self.fetchTweets(company: self.hashes[self.selectedCompanyIndex])
    group.leave()
}
group.notify(queue: .main) {
     print("done")
}

//function for fetching tweets
func fetchTweets(company: String) {

        swifter.searchTweet(
            using: company,
            lang: "en",
            count: 100,
            tweetMode: .extended,
            success: { (results, metadata) in
                var tweets = [TextClassifier1Input]()
                for i in 0...99 {
                    if let tweet = results[i]["full_text"].string {
                        tweets.append(TextClassifier1Input(text: tweet))
                    }
                }
                let searchType = String(company.first!)
                self.makePrediction(with: tweets, type: searchType)
        }) { (error) in
            print("There was an error with the Twitter API: --> ", error)
        }
    }

//function for making predictions via the coreML model
func makePrediction(with tweets: [TextClassifier1Input], type: String) {
        do {
            let predictions = try self.sentimentClassifier.predictions(inputs: tweets)
            var sentimentScore = 0
            for pred in predictions {
                if pred.label == "pos" {
                    sentimentScore += 1
                } else if pred.label == "neg" {
                    sentimentScore -= 1
                } else {
                    print("something sent wrong: --> ", pred.label)
                }
            }
            if type == "@" {
                arobaseScore = sentimentScore
            } else if type == "#" {
                hashScore = sentimentScore
            }
        } catch {
            print("There was an error with the ML model: --> ", error)
        }
    }

问题是导航是在单击按钮时执行的,而我希望之前完成之前的操作。 谁能告诉我应该如何使用 DispatchGroups 和 DispatchQueue 以正确的顺序运行我的代码

提前感谢您的帮助

【问题讨论】:

    标签: ios swift asynchronous


    【解决方案1】:

    欢迎使用 Stack Overflow。

    在进行更新之前,您无需等待 swifter.searchTweet 完成。

    第一步是将完成处理程序添加到fetchTweets。完成处理程序是在fetchTweets 完成网络时报告的一种方式。

    //function for fetching tweets
    func fetchTweets(company: String, completion: @escaping () -> Void) {
                                   // ^^^^^^^^^^ Added completion handler
    
            swifter.searchTweet(
                using: company,
                lang: "en",
                count: 100,
                tweetMode: .extended,
                success: { (results, metadata) in
                    var tweets = [TextClassifier1Input]()
                    for i in 0...99 {
                        if let tweet = results[i]["full_text"].string {
                            tweets.append(TextClassifier1Input(text: tweet))
                        }
                    }
                    let searchType = String(company.first!)
                    self.makePrediction(with: tweets, type: searchType)
                    completion() // <-- Call completion on success
            }) { (error) in
                print("There was an error with the Twitter API: --> ", error)
                completion() // <-- Call completion on failure
            }
        }
    
    

    完成后,即可在组网完成后进出群组。然后将调用 notify 中的代码。它位于您需要更新 UI 的代码块中。

    let group = DispatchGroup()
    
    self.name = self.names[self.selectedCompanyIndex]
    
    group.enter()
    self.fetchTweets(company: self.arobases[self.selectedCompanyIndex]) {
        group.leave() // <-- leave the group in the completion handler
    }
    
    group.enter()
    self.fetchTweets(company: self.hashes[self.selectedCompanyIndex]) {
        group.leave() // <-- leave the group in the completion handler
    }
    
    group.notify(queue: .main) {
         print("done")
         // BEGIN UPDATING THE UI
         // NOTE: Here is where you update the UI.
         // END UPDATING THE UI
    }
    

    【讨论】:

    • 感谢您的回答。我没有考虑完成处理程序,它现在正在工作
    • @AlexeyMoulinov 在 Stack Overflow 上,您应该接受并支持对您有用的答案,我非常感谢您的接受和支持。
    【解决方案2】:

    对于那些使用编程导航的人来说,在调用后端之前尝试导航会导致各种问题,即视图希望在调用结束之前仍然停留并且您的导航逻辑想要继续

    【讨论】:

    猜你喜欢
    • 2021-06-03
    • 2019-10-29
    • 2014-12-07
    • 1970-01-01
    • 2022-01-22
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多