iOS - SwiftUI - 执行异步操作后导航到下一个屏幕

Posted

技术标签:

【中文标题】iOS - SwiftUI - 执行异步操作后导航到下一个屏幕【英文标题】:iOS - SwiftUI - Navigate to the next screen AFTER async actions performed 【发布时间】: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 以正确的顺序运行我的代码

提前感谢您的帮助

【问题讨论】:

【参考方案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】:

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

【讨论】:

这没有提供问题的答案。一旦你有足够的reputation,你就可以comment on any post;相反,provide answers that don't require clarification from the asker。 - From Review

以上是关于iOS - SwiftUI - 执行异步操作后导航到下一个屏幕的主要内容,如果未能解决你的问题,请参考以下文章

ios 13 SwiftUI向后导航时如何避免导航视图内的TabView应用崩溃

iOS14中点击SwiftUI列表项导航跳转返回后外观呈灰色的解决

如何在 SwiftUI 中动态隐藏导航返回按钮

单击按钮后立即执行 SwiftUI 按钮操作,而不是单击释放

使用 SwiftUI 成功登录后导航

SwiftUI导航至子视图后状态改变导致导航栈提前弹出的原因及解决