简体   繁体   English

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

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

How to receive an output of an array of [TweetSentimentClassifierInput] objects to send it further to my prediction model?如何接收 [TweetSentimentClassifierInput] 对象数组的 output 以将其进一步发送到我的预测 model?

I have the array but inside a closure which turns it unavailable to return as a method output.我有数组,但在一个闭包中,这使它无法作为方法 output 返回。 If I initialize an empty array outside the closure then the output is always an empty array since fetch closure takes time to be completed.如果我在闭包之外初始化一个空数组,那么 output 始终是一个空数组,因为 fetch 闭包需要时间才能完成。

Code代码

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)")
    }
}
}

How can I return a non-empty array from a closure as a method output?如何从闭包中返回非空数组作为方法 output?

You should use a completionHandler concept to achieve async operations like this:您应该使用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)
        }
    }
}

Usage用法

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

Convert this method in async, passing closure with [TweetSentimentClassifierInput] as closure argument, and an error as secondary closure argument,将此方法异步转换,以[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)
    }
}

You need a completion handler.您需要一个完成处理程序。

The modern Result type which can contain both the good data and an error provides a convenience initializer to catch the DecodingError implicitly现代的Result类型可以同时包含好的数据和错误,它提供了一个方便的初始化器来隐式捕获DecodingError

struct TweetFetcher {
    
    let tweetCount = 100
    let swifter = Swifter(consumerKey: key, consumerSecret: secret)
    
    func fetchTweets(with searchText: String, completion: @escaping (Result<[TweetSentimentClassifierInput], Error>) -> Void) {
        
        swifter.searchTweet(using: searchText, lang: "en", count: tweetCount, tweetMode: .extended) {(results, searchMetadata) in
            completion( Result {
                try JSONDecoder().decode([TweetData].self, from: Data(results.description.utf8))
                    .map{TweetSentimentClassifierInput(text: $0.full_text)}
            })
        } failure: { completion(.failure($0)) }
    }
}

And call it并称它为

fetchTweets(with: "Foo") { result in
    switch result {
        case .success(let input): print(input)
        case .failure(let error): print(error)
    }
}

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

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