2017-05-28 118 views
1

我试图使用的方法以外的一些JSON响应,但返回时,执行方法空数组,但随着预期的数据块的作品里面,有没有什么办法我的方法将返回预期值,这是我的示例代码:如何使用DispatchSemaphore与Alamofire和SwiftyJSON?

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方法设计为调用代码,直到网络请求完成,这可能需要很长的时间。 如果你打算从你的应用程序主线程调用这个方法这样必然会造成了极坏的UX。我们来看看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)") 
} 
+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) 
} 
相关问题