2016-04-06 12 views
1

私は現在、1台のコンテナViewControllerを管理しています。ViewControllerUIScrollViewというコンテナ内に複数の子ViewControllersを管理しています。Swift NSURLSession:同時に複数のリクエストを実行しているときに問題が発生しました

それぞれの子VCには、すべての気象情報を保持するクラスであるlocationプロパティがあります。このクラスは、OpenWeatherMapsのAPIからデータをロードするため、以下の機能があります。

func refresh(completionHandler:() ->()) { 
    let session = NSURLSession.sharedSession() 
    session.dataTaskWithURL(self._apiUrl) { (responseData: NSData?, response:NSURLResponse?, error: NSError?) -> Void in 
     if let data = responseData { 
      do { 
       let json: AnyObject = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) 
       // parse json 
       completionHandler() 
      } catch let err as NSError { 
       print(err.debugDescription) 
      } 
     } 
    }.resume() 
} 

その後子供VCは、私は、ユーザーインターフェイスを更新していますので、completionHandlerは(メインスレッド上で実行されていると、他の関数を呼び出す機能を持っています):

func refreshWeatherData() { 
    location.refresh { 
     dispatch_async(dispatch_get_main_queue(), { 
      print("\(self.location.name)") 
      self.forecastCollectionView.reloadData() 
     }) 
    } 
} 

そして最後にContainerVCから、私はすべての私のLocationVCsにrefreshWeatherData関数を呼び出しています。

override func viewDidLoad() { 
    super.viewDidLoad() 
    let zurich = WALocation(name: "Zürich", id: "7287650", country: "CH", longitude: 8.53071) 
    let shanghai = WALocation(name: "Shanghai", id: "1796236", country: "CN", longitude: 121.45) 
    let boston = WALocation(name: "Boston", id: "4183849", country: "US", longitude: -83.78) 
    let vancouver = WALocation(name: "Vancouver", id: "6173331", country: "CA", longitude: -123.11) 

    addLocationControllerForLocation(shanghai) 
    locationControllers[0].refreshWeatherData() 
    addLocationControllerForLocation(boston) 
    locationControllers[1].refreshWeatherData() 
    addLocationControllerForLocation(zurich) 
    locationControllers[2].refreshWeatherData() 
    addLocationControllerForLocation(vancouver) 
    locationControllers[3].refreshWeatherData() 
} 

今、私が遭遇した問題は、時には(常にではない)、1 2または3回、JSONSerialisationは(場所のリフレッシュ機能で)エラーがスローされますということです。 Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo ``{NSDebugDescription=No value.} 場合は代わりに私のContainerVC Iでこれを行う:

override func viewDidLoad() { 
    super.viewDidLoad() 
    let zurich = WALocation(name: "Zürich", id: "7287650", country: "CH", longitude: 8.53071) 
    let shanghai = WALocation(name: "Shanghai", id: "1796236", country: "CN", longitude: 121.45) 
    let boston = WALocation(name: "Boston", id: "4183849", country: "US", longitude: -83.78) 
    let vancouver = WALocation(name: "Vancouver", id: "6173331", country: "CA", longitude: -123.11) 

    addLocationControllerForLocation(shanghai) 
    locationControllers[0].refreshWeatherData() 
    sleep(1) 
    addLocationControllerForLocation(boston) 
    locationControllers[1].refreshWeatherData() 
    sleep(1) 
    addLocationControllerForLocation(zurich) 
    locationControllers[2].refreshWeatherData() 
    sleep(1) 
    addLocationControllerForLocation(vancouver) 
    locationControllers[3].refreshWeatherData() 
} 

NSJSONSerialisationは失敗しません。これは、複数のリクエストが非同期で実行されている場合にのみ失敗すると考えています。

ご協力いただければ幸いです。

+0

ここで(実際には**の場合は)気象データを保存しますか? – vadian

+0

リフレッシュ機能のdoブロックにコメントを書いてパースするときに保存します – Nico

答えて

0

これはスレッドの問題のようです。 GCDコールでリフレッシュコールを囲む(またはリフレッシュする)ことを試みましたか?例:

dispatch_syncを使用することができます。

どちらの方法でも、completionHandlerが正しいスレッドで必要なものをコールバックしていることを確認してください。それがUIアップデートの場合は、メインスレッドです。

編集 以下の記事から続きを読むと、refreshHandlerのデータが返されます。

func refresh(completionHandler: (AnyObject) ->()) { //Anyobject being your JsonData or whatever so could be NSString, String, etc... 
    let session = NSURLSession.sharedSession() 
    session.dataTaskWithURL(self._apiUrl) { (responseData: NSData?, response:NSURLResponse?, error: NSError?) -> Void in 
     if let data = responseData { 
      do { 
       let json: AnyObject = try NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments) 
       // parse json 
       completionHandler(json) 
      } catch let err as NSError { 
       print(err.debugDescription) 
      } 
     } 
    }.resume() 
} 
+0

私はすでにこれを試してみましたが、それは役に立たない。私がそれを動作させる唯一の方法は、その場所のcompletionHandlerブロック内の次の場所をリフレッシュすることです。 – Nico

+0

'self.location'呼び出しと何かのように見えます。それよりもむしろ、補完ハンドラを介して値を返すほうがよいでしょうか?私は私の答えのポストの例を挙げます。 –

+0

これを使用すると、返されるものは何でも完了ハンドラに送信されることが保証されます...本当にスレッディングについて心配する必要はありません –

関連する問題