2017-11-29 8 views
0

私はサーバーから取得したデータをJSONで解析しています。だから、私はURLセッションを持っています。このデータは、受信した辞書のキーと同じ構造体を使用するため、正しく解析されますが、このデータをこのオブジェクトに変換すると、このオブジェクトを保存できません完了ハンドラのスコープ外の配列完了ハンドラの値/オブジェクトをその外にある配列に取得します

使用機能:

fileprivate func loadColor(_ urlString: URL?, completionHandler: @escaping (Color) -> Void) { 
    if let url = urlString { 

     let task = URLSession.shared.dataTask(with: url) { (data, response, error) in 
      if error != nil { 
       print(error) 
      } else { 


       do { 
        if let data = data, 
         let color = try JSONSerialization.jsonObject(with: data) as? [String: Any] { 
         guard let color2 = Color(json: color) else 
         { 
          fatalError("something didn't go as planned") 
         } 

         completionHandler(color2) 
        } 
       } catch { 
        print("Error deserializing JSON: \(error)") 
       } 

      } 
     } 
     task.resume() 

    } 

} 

私は(のviewDidLoadでこのメソッドを呼び出した)、このような配列にそれを取得しよう:私は色の配列にそれを追加実行すると

var colors : [Color] = [] 

override func viewDidLoad() { 
    super.viewDidLoad() 

    loadColor(URL(string: "API command here"), completionHandler: { color in 

     self.colors.append(color) 
     print("\(self.colors.count)") 
    }) 
    print("\(self.colors.count)") 

} 

カウントを出力するときに0から1になるので、配列に追加しますが、この完了ハンドラのスコープの外に出ると、配列は再び空になります。 私は何が欠けていますか?

+0

アレイを更新していますが、ネットワークコードが非同期で完了しているため、値がネットワークから取得されてアレイに追加される前にアレイを印刷しています。クロージャー内のコードから配列内の値にアクセスするか、クロージャーによって呼び出されるだけです。 – Paulw11

+0

それでは、これをどうやって修正するべきですか?何らかの待機方法を実行する必要がありますか? – symenize

+0

いいえ、私が言ったように、あなたが閉鎖か閉鎖から呼び出す関数のいずれかで配列と何をする必要があれば何でもしてください。 – Paulw11

答えて

0

printネットワーキングコール外の文が0値を出力している理由は、そのAPI呼び出しが非同期であるため、そのprint文が実行された後に終了するためです。配列が本当に空の配列に戻されている場合は、別の場所で起こっているはずです。デバッグのために何ができる

ことの一つは、おそらく、それはこのように設定されているときに見て、その変数を観察することです:

var colors: [Color] = [] { 
    didSet { 
    //This will be called every time this array is set/changed 
    print(colors.count) 
    } 
} 

ように、あなたもdidSet内print文にブレークポイントを置くことができますあなたの配列をリセットしているもののトレースを見ることができます。

また、私はあなたのコードが問題ないと思っていますが、その非同期完了のタイミングについてちょっと混乱しています。

+0

ああ、私はこれについて全く考えなかった。実際には、値/オブジェクトがそこにあることを示しています。ありがとうございます!しかし、別のタスクを実行したいときにこの配列が必要なときに、この非同期性をどのように扱うべきですか?つまり、範囲外のエラーのインデックスを避けるためにこのタスクが完了するのを待つ方法はありますか? – symenize

+0

'didSet'で実行するもう一つの完璧な仕事!今、カウントを印刷する代わりに、あなたはその新たに更新された配列を取って、必要なものを何でもすることができます。それは理にかなっていますか? – creeperspeak

+0

はい、APIから受け取ったすべての要素が配列に追加される代わりに、要素が追加されるたびにそのタスクが実行されますか?私はこの質問には言及しませんでしたが、最終的には、この配列を使用してコレクションビューセルをこの配列の色で更新したいと考えています。 – symenize

関連する問題