2016-03-26 9 views
0

私は、APIからデータを取得し、それをtableviewインスタンスに表示する単純なFlickrアプリケーションを開発中です。 TableViewControllerサブクラスのコードの一部です。iOS - 最初のアプリケーションの読み込み時にreloadData tableViewデータが表示されるのはなぜですか?

var photos = [FlickrPhotoModel]() 

override func viewDidLoad() { 
    super.viewDidLoad() 
    getFlickrPhotos() 
} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
} 
private func getFlickrPhotos() { 
    DataProvider.fetchFlickrPhotos { (error: NSError?, data: [FlickrPhotoModel]?) in 

     //data is received 
     dispatch_async(dispatch_get_main_queue(), { 
      if error == nil { 
       self.photos = data! 
       self.tableView.reloadData() 
      } 
     }) 
    } 
} 

{tableView.reloadData()}行が削除された場合、アプリケーションはデータをロードしていないようです。私はviewDidLoad()内でgetFlickrPhotos()を呼び出して以来、誰がなぜこのようなことが起こるか知っていますか?私はまた、適切な場所にバックグラウンドスレッドからディスパッチしていると思います。私が間違っていることを教えてください。

EDIT - データプロバイダのコード

class func fetchFlickrPhotos(onCompletion: FlickrResponse) { 
    let url: NSURL = NSURL(string: "https://api.flickr.com/services/rest/?method=flickr.photos.getRecent&api_key=\(Keys.apikey)&per_page=25&format=json&nojsoncallback=1")! 

    let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in 

     if error != nil { 
      print("Error occured trying to fetch photos") 
      onCompletion(error, nil) 
      return 
     } 

     do { 

      let jsonResults = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary 
      let photosContainer = jsonResults!["photos"] as? NSDictionary 
      let photoArray = photosContainer!["photo"] as? [NSDictionary] 

      let flickrPhoto: [FlickrPhotoModel] = photoArray!.map{ 
       photo in 

       let id = photo["id"] as? String ?? "" 
       let farm = photo["farm"] as? Int ?? 0 
       let secret = photo["secret"] as? String ?? "" 
       let server = photo["server"] as? String ?? "" 
       var title = photo["title"] as? String ?? "No title available" 
       if title == "" { 
        title = "No title available" 
       } 

       let model = FlickrPhotoModel(id: id, farm: farm, server: server, secret: secret, title: title) 
       return model 
      } 

      //the request was successful and flickrPhoto contains the data 
      onCompletion(nil, flickrPhoto) 



     } catch let conversionError as NSError { 
      print("Error parsing json results") 
      onCompletion(conversionError, nil) 

     } 
    } 
    task.resume() 

} 

答えて

3

私はそのAPIに精通していないんだけど、fetchFlickrPhotosメソッドはバックグラウンドスレッドで非同期的に呼び出されたように見えます。つまり、アプリケーションの残りの部分は、移動する前に終了するのを待つことはありません。 viewDidLoadはメソッドを呼び出しますが、終了するのを待つことなく移動します。

あなたが提供する完了ハンドラは、写真がダウンロードされたの後にと呼ばれ、写真の数とサイズに応じて秒後になる可能性があります。したがって、写真が実際にダウンロードされた後でテーブルビューを更新するには、reloadDataが必要です。

+0

fetchFlickrPhotosがバックグラウンドスレッドで呼び出されたことをどう思いますか?元の投稿を編集して、DataProviderクラスのコードを追加しました。それはNSUrlSessionがバックグラウンドスレッドで実行されるためですか? –

+1

いくつかの理由...まず、コールバック関数が含まれています。コールバックを持つ唯一の理由は、関数が非同期である場合です。また、テーブルビューを更新する前に、コールバックはメインキューを取得します。つまり、メインキュー以外で実行していたはずです。最後に、かなり一般的なパターンです...大規模なダウンロードは、非同期的にバックグラウンドで行われ、メインキューをブロックしないようにする必要があります。 –

+0

ありがとうローマ!あなたがそのように説明したので、これは非常に意味があります。私はあなたにこのコードを送って、それをさらに改善することができますか?私はgithubでまだそれを持っていないので、私は電子メールでそれを送ることができます。あなたの電子メールアドレスを[email protected]に送信することができます。ありがとう、トン! –

関連する問題