异步请求完成前的函数 returns
Function returns before asynchronous request finishes
我正在使用 Twitter API 检索推文列表。该方法应该 return 推文列表,但问题是它在请求结束前 returns,这导致空列表被 returned。我该如何解决?这是该方法的源代码:
// Call to search through twitter with a query
func searchQuery(query: String) -> [Tweet] {
var tweets: [Tweet] = []
var query_URL = query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
if let query_URL = query_URL {
TwitterClient.sharedInstance.GET("https://api.twitter.com/1.1/search/tweets.json?q=\(query_URL)", parameters: nil, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
tweets = parseJSON(response)
println(tweets.count)
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
})
}
println("ret: \(tweets.count)")
return tweets
}
在上面的代码中,输出将是
ret: 0
15
我试过使用调度组,但我无法让它们工作。这是我对 GCD 所做的:
// Call to search through twitter with a query
func searchQuery(query: String) -> [Tweet] {
var tweets: [Tweet] = []
var query_URL = query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
var group = dispatch_group_create()
if let query_URL = query_URL {
dispatch_group_enter(group)
TwitterClient.sharedInstance.GET("https://api.twitter.com/1.1/search/tweets.json?q=\(query_URL)", parameters: nil, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
tweets = parseJSON(response)
dispatch_group_leave(group)
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
dispatch_group_leave(group)
})
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
return tweets
}
但是,该代码似乎永远等待。
作为参考,Tweet
是一个用于保存与推文相关的数据的结构。我用它以更紧凑的方式移动大量数据。 parseJSON 根据 JSON 响应填充并 returns 一组推文。理想情况下,returned 数组将被保存到 tweets
,然后应该从该方法中 return,但这并没有发生。
任何解决这个问题的想法或技术将不胜感激!
编辑:@Hamza Ansari
这是实际功能:
// Call to search through twitter with a query
func searchQuery(query: String, completionHandler:(returntweets: [Tweet]) -> Void) {
var query_URL = query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
if let query_URL = query_URL {
TwitterClient.sharedInstance.GET("https://api.twitter.com/1.1/search/tweets.json?q=\(query_URL)", parameters: nil, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
var tweets:[Tweet] = parseJSON(response)
println("size in method: \(tweets.count)")
completionHandler(returntweets: tweets)
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
})
}
}
但是,当调用用于初始化数据源的不同方法时:
// Initializes the data source
func initialize(query: String) {
self.query = query
searchQuery(query, { (returnTweets) -> Void in
self.searches = returnTweets
})
println("size when called: \(searches.count)")
}
输出(按顺序):
size when called: 0
size in method: 15
用完成处理程序定义函数:
func searchQuery(query: String, completionHandler:(returntweets: [Tweet]) -> Void) {
var query_URL = query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
if let query_URL = query_URL {
TwitterClient.sharedInstance.GET("https://api.twitter.com/1.1/search/tweets.json?q=\(query_URL)", parameters: nil, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
var tweets:[Tweet] = parseJSON(response)
println(tweets.count)
completionHandler(returntweets: tweets)
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
})
}
}
现在在需要推文的地方调用它:
searchQuery(query: "youQuery",{ (returntweets) -> Void in
//Do something
println(returntweets.count)
}
这是设计使然;这是一个 "asynchronous" 方法(即,它启动并执行一些工作,并在完成后调用您提供的 "success" 代码)。之所以这样设计,是因为您的主线程 不会 因等待网络而被阻塞,这可能会花费不确定的时间。
这需要您相应地围绕它设计代码——您不能真正拥有一个方法来做您想要的(您称之为,它returns 准备好结果)。好吧,你可以(通过在后台线程上排队异步调用然后等待它)但是你会等待你不想做的网络。相反,你应该改变你自己的方法 searchQuery
来做类似的事情(异步)并且它的调用者应该根据需要处理它。
当需要完成异步工作时,这种模式既可以接受又很好,而且一旦您习惯了它,它并不像最初看起来那么繁重。
(请参阅@HamzaAnsari 的回答,了解如何执行此操作。)
我正在使用 Twitter API 检索推文列表。该方法应该 return 推文列表,但问题是它在请求结束前 returns,这导致空列表被 returned。我该如何解决?这是该方法的源代码:
// Call to search through twitter with a query
func searchQuery(query: String) -> [Tweet] {
var tweets: [Tweet] = []
var query_URL = query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
if let query_URL = query_URL {
TwitterClient.sharedInstance.GET("https://api.twitter.com/1.1/search/tweets.json?q=\(query_URL)", parameters: nil, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
tweets = parseJSON(response)
println(tweets.count)
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
})
}
println("ret: \(tweets.count)")
return tweets
}
在上面的代码中,输出将是
ret: 0
15
我试过使用调度组,但我无法让它们工作。这是我对 GCD 所做的:
// Call to search through twitter with a query
func searchQuery(query: String) -> [Tweet] {
var tweets: [Tweet] = []
var query_URL = query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
var group = dispatch_group_create()
if let query_URL = query_URL {
dispatch_group_enter(group)
TwitterClient.sharedInstance.GET("https://api.twitter.com/1.1/search/tweets.json?q=\(query_URL)", parameters: nil, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
tweets = parseJSON(response)
dispatch_group_leave(group)
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
dispatch_group_leave(group)
})
}
dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
return tweets
}
但是,该代码似乎永远等待。
作为参考,Tweet
是一个用于保存与推文相关的数据的结构。我用它以更紧凑的方式移动大量数据。 parseJSON 根据 JSON 响应填充并 returns 一组推文。理想情况下,returned 数组将被保存到 tweets
,然后应该从该方法中 return,但这并没有发生。
任何解决这个问题的想法或技术将不胜感激!
编辑:@Hamza Ansari 这是实际功能:
// Call to search through twitter with a query
func searchQuery(query: String, completionHandler:(returntweets: [Tweet]) -> Void) {
var query_URL = query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
if let query_URL = query_URL {
TwitterClient.sharedInstance.GET("https://api.twitter.com/1.1/search/tweets.json?q=\(query_URL)", parameters: nil, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
var tweets:[Tweet] = parseJSON(response)
println("size in method: \(tweets.count)")
completionHandler(returntweets: tweets)
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
})
}
}
但是,当调用用于初始化数据源的不同方法时:
// Initializes the data source
func initialize(query: String) {
self.query = query
searchQuery(query, { (returnTweets) -> Void in
self.searches = returnTweets
})
println("size when called: \(searches.count)")
}
输出(按顺序):
size when called: 0
size in method: 15
用完成处理程序定义函数:
func searchQuery(query: String, completionHandler:(returntweets: [Tweet]) -> Void) {
var query_URL = query.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
if let query_URL = query_URL {
TwitterClient.sharedInstance.GET("https://api.twitter.com/1.1/search/tweets.json?q=\(query_URL)", parameters: nil, success: { (operation: AFHTTPRequestOperation!, response: AnyObject!) -> Void in
var tweets:[Tweet] = parseJSON(response)
println(tweets.count)
completionHandler(returntweets: tweets)
}, failure: { (operation: AFHTTPRequestOperation!, error: NSError!) -> Void in
})
}
}
现在在需要推文的地方调用它:
searchQuery(query: "youQuery",{ (returntweets) -> Void in
//Do something
println(returntweets.count)
}
这是设计使然;这是一个 "asynchronous" 方法(即,它启动并执行一些工作,并在完成后调用您提供的 "success" 代码)。之所以这样设计,是因为您的主线程 不会 因等待网络而被阻塞,这可能会花费不确定的时间。
这需要您相应地围绕它设计代码——您不能真正拥有一个方法来做您想要的(您称之为,它returns 准备好结果)。好吧,你可以(通过在后台线程上排队异步调用然后等待它)但是你会等待你不想做的网络。相反,你应该改变你自己的方法 searchQuery
来做类似的事情(异步)并且它的调用者应该根据需要处理它。
当需要完成异步工作时,这种模式既可以接受又很好,而且一旦您习惯了它,它并不像最初看起来那么繁重。
(请参阅@HamzaAnsari 的回答,了解如何执行此操作。)