[英]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.