我试图在方法之外使用一些json响应,但是当执行方法时它返回空数组,但是在块内部按预期工作,我的方法是否会返回预期值,这是我的示例代码:< / p>
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。仅供参考我是新手,并尝试过类似问题的回答,但没有成功,任何建议都非常感谢,谢谢。
答案 0 :(得分: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)
}
答案 1 :(得分: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)")
}