如何将 DispatchSemaphore 与 Alamofire 和 SwiftyJSON 一起使用?
Posted
技术标签:
【中文标题】如何将 DispatchSemaphore 与 Alamofire 和 SwiftyJSON 一起使用?【英文标题】:How to use DispatchSemaphore with Alamofire and SwiftyJSON? 【发布时间】:2017-05-28 19:53:23 【问题描述】:我试图在方法外部使用一些 json 响应,但是在执行方法时它返回空数组,但在块内部按预期工作,有什么方法可以返回预期值,这是我的示例代码:
func getCarouselContent(url: String) -> [String]
var ids: [String] = []
let headers = ["api_key": "My_API_KEY"]
let semaphore = DispatchSemaphore(value: 0)
Alamofire.request(url, headers: headers).validate().responseJSON
(response) in
semaphore.signal()
switch response.result
case .success(let value):
let json = JSON(value)
let data = json["data"]["relationships"]["slides"]["data"]
for child in data.array!
let id = child["id"].string!
print(id) // this prints all the id
ids.append(id)
case .failure(let error):
print(error)
semaphore.wait()
return ids
我正在使用 alamofire 和 swiftyjson 来解析 json。仅供参考,我对此很陌生,并尝试了类似问题的回复中的解决方案,但没有奏效,非常感谢任何建议,谢谢。
【问题讨论】:
【参考方案1】:将解决您的原始问题然后提供更好的解决方案:
信号量。您可能过早地发出信号。当从函数/闭包返回时,安全地发出DispatchSemaphore
信号的一个健壮习惯用法是使用defer
语句。例如:
Alamofire.request(url, headers: headers).validate().responseJSON
(response) in
defer
semaphore.signal() // Executed before leaving current scope.
...
这可确保您始终独立于退出点触发 signal()
,避免死锁。
话虽如此,这可能远非最佳解决方案......
完成处理程序。您设计了 getCarouselContent
方法来阻止调用代码,直到完成网络请求,这可能需要(非常!)很长时间。 如果您打算从您的应用程序主线程调用此方法,这肯定会导致非常糟糕的用户体验。来看看Apple says about this:
请务必限制您在应用主线程上执行的工作类型。主线程是您的应用处理触摸事件和其他用户输入的地方。为确保您的应用始终响应用户,您不应使用主线程来执行长时间运行或可能无限制的任务,例如访问网络的任务。相反,您应该始终将这些任务移至后台线程。
一个常见的模式是将一个完成块传递给你的getCarouselContent
方法。当 JSON 响应最终到达时,该块将被传递结果。例如:
func getCarouselContent(url: String, completion: @escaping ([String]) -> Void)
let headers = ["api_key": "My_API_KEY"]
Alamofire.request(url, headers: headers).validate().responseJSON
(response) in
var ids = [String]()
switch response.result
case .success(let value):
let json = JSON(value)
let data = json["data"]["relationships"]["slides"]["data"]
for child in data.array!
ids.append(child["id"].string!)
case .failure(let error):
print(error)
completion(ids)
然后这样称呼它:
getCarouselContent(url: someUrl)
(ids) in
print("IDs received: \(ids)")
【讨论】:
【参考方案2】:忘记信号量来解决方法的异步行为。学习理解异步模式并使用完成处理程序:
func getCarouselContent(url: String, completion: ([String])->())
var ids = [String]()
let headers = ["api_key": "My_API_KEY"]
Alamofire.request(url, headers: headers).validate().responseJSON response in
switch response.result
case .success(let value):
let json = JSON(value)
let data = json["data"]["relationships"]["slides"]["data"]
for child in data.array!
let id = child["id"].string!
print(id) // this prints all the id
ids.append(id)
case .failure(let error):
print(error)
completion(ids)
并称它为:
getCarouselContent(url: <someURL>) identifiers in
print(identifiers)
【讨论】:
以上是关于如何将 DispatchSemaphore 与 Alamofire 和 SwiftyJSON 一起使用?的主要内容,如果未能解决你的问题,请参考以下文章
Swift DispatchSemaphore 正在冻结应用程序
如何正确使用信号灯同步 Alamofire 请求 Swift4 的主线程?