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

How to receive an output for a method from a closure in Swift?

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

我有数组,但在一个闭包中,这使得它无法作为方法输出 return。如果我在闭包外初始化一个空数组,那么输出总是一个空数组,因为 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)")
    }
}
}

如何 return 闭包中的非空数组作为方法输出?

以异步方式转换此方法,以 [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)
    }
}

您应该使用 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 ...
    }
}