2017-05-28 90 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) 
} 
相關問題