如何从 Swift 的闭包中接收方法的输出?

Posted

技术标签:

【中文标题】如何从 Swift 的闭包中接收方法的输出?【英文标题】:How to receive an output for a method from a closure in Swift? 【发布时间】:2022-01-10 09:39:38 【问题描述】:

如何接收 [TweetSentimentClassifierInput] 对象数组的输出以进一步发送到我的预测模型?

我有数组,但在一个闭包中,这使它无法作为方法输出返回。如果我在闭包之外初始化一个空数组,那么输出始终是一个空数组,因为 fetch 闭包需要时间才能完成。

代码

struct TweetFetcher 

   let tweetCount = 100
   let swifter = Swifter(consumerKey: key, consumerSecret: secret)

func fetchTweets(with searchText: String) -> [TweetSentimentClassifierInput] 
    
    swifter.searchTweet(using: searchText, lang: "en", count: tweetCount, tweetMode: .extended) (results, searchMetadata) in
        var tweets = [TweetSentimentClassifierInput]()
        let data = results.description.data(using: .utf8)

        do 
            let decodedData = try JSONDecoder().decode([TweetData].self, from: data!)
         catch 
            print("Error with decoding, \(error)")
        

        for tweet in decodedData 
            let tweetForClassification = TweetSentimentClassifierInput(text: tweet.full_text)
            tweets.append(tweetForClassification)
        
     failure:  (error) in
        print("Error with the Twitter API request, \(error)")
    


如何从闭包中返回一个非空数组作为方法输出?

【问题讨论】:

异步转换此方法,以 [TweetSentimentClassifierInput] 作为闭包参数传​​递闭包 您可以将自己的闭包/回调参数添加到 fetchTweets 并将其作为参数传递给该闭包,或者将属性添加到您在闭包中分配数组的结构 不相关,但您的代码无法编译。循环必须在do 范围内。 @vadian,谢谢。是的,你是对的。只是忘记移动它,这是强制尝试测试:) 【参考方案1】:

将此方法异步转换,以[TweetSentimentClassifierInput] 作为闭包参数传​​递闭包,并将错误作为辅助闭包参数,

func fetchTweets(with searchText: String, finished: ((_ sentiments: [TweetSentimentClassifierInput]?,_ error: Error?) -> Void)) 

    swifter.searchTweet(using: searchText, lang: "en", count: tweetCount, tweetMode: .extended) (results, searchMetadata) in
        var tweets = [TweetSentimentClassifierInput]()
        let data = results.description.data(using: .utf8)

        do 
           let decodedData = try JSONDecoder().decode([TweetData].self, from: data!)
            catch 
           print("Error with decoding, \(error)")
        

        for tweet in decodedData 
            let tweetForClassification = TweetSentimentClassifierInput(text: tweet.full_text)
            tweets.append(tweetForClassification)
        
        finished(tweets, nil)
     failure:  (error) in
        print("Error with the Twitter API request, \(error)")
        finished(nil, error)
    

【讨论】:

谢谢你,雷尼尔。但是如果我需要稍后在 ViewController 中调用 fetchTweets 怎么办?然后我应该给这个方法一个我在那个 VC 中没有的情感部分。现在我认为将我的 fetch 和 predict 方法结合起来可能会更容易,这样我就可以像在哪里完成(tweets,nil)一样传递数组......【参考方案2】:

您应该使用completionHandler 概念来实现这样的异步操作:

struct TweetFetcher 
    let tweetCount = 100
    let swifter = Swifter(consumerKey: key, consumerSecret: secret)
    
    func fetchTweets(with searchText: String, completion: @escaping ([TweetSentimentClassifierInput]?, Error?) -> Void) 
        
        swifter.searchTweet(using: searchText, lang: "en", count: tweetCount, tweetMode: .extended) (results, searchMetadata) in
            var tweets = [TweetSentimentClassifierInput]()
            let data = results.description.data(using: .utf8)
            
            do 
                let decodedData = try JSONDecoder().decode([TweetData].self, from: data!)
             catch 
                print("Error with decoding, \(error)")
                completion(nil, error)
            
            
            for tweet in decodedData 
                let tweetForClassification = TweetSentimentClassifierInput(text: tweet.full_text)
                tweets.append(tweetForClassification)
            
            completion(tweets, nil)
         failure:  (error) in
            print("Error with the Twitter API request, \(error)")
            completion(nil, error)
        
    

用法

let fetcher = TweetFetcher()
fetcher.fetchTweets(with: "Keyword...")  tweets, error in
    if let error = error 
        print(error.localizedDescription)
     else 
        // Use tweets array content here ...
    

【讨论】:

非常感谢!我在项目中进行了一些更改,成功实现了您的答案。我以前从未使用过 completionHandler 的概念(说实话,我只是 Swift 的新手)。你能推荐一些文章来更深入地理解这个概念吗? 不客气。实际上,完成处理程序是closures 的一种形式,所以我认为您应该知道闭包是如何工作的,以便更好地理解它。可以在 here 和 here 找到一个很好的完成处理程序教程

以上是关于如何从 Swift 的闭包中接收方法的输出?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用接收数据作为参数的函数的闭包范围?

Swift:如何从服务器接收远程通知?

如何从 iOS 中的流中接收数据(swift)

使用Multipeer Connectivity(Swift 2)从发件人的目标iPhone中部分接收音频文件

如何从从 Firebase 检索信息的闭包中传递数据?

Swift:如何将从委托接收到的值传递给函数的完成块?