Search code examples
iosswiftalamofire

Table View not updating with data fetched by HTTP Request


I'm trying to populate a table view with data fetched from a http request (JSON) but it's not working. If I populate the Table View with static data everything works fine.. code snippet:

import UIKit
import Alamofire
//import SwiftyJSON

class ViewControllerNews : UITableViewController{
@IBOutlet var table: UITableView!

var posts = [FacebookPost]()

override func viewDidLoad() {
    pullFacebookNews()
    //loadSampleNews()
    super.viewDidLoad()

}

func pullFacebookNews() -> Void {


    let params = ["limit":"100", "access_token": myaccesstoken]


   Alamofire.request( "https://graph.facebook.com/<page-id>/posts", parameters: params).responseJSON{ response in

    if let responsejson = response.result.value {
        let JSON = responsejson as! NSDictionary
        let itemsArray: NSArray? = JSON.object(forKey: "data") as? NSArray

        if(itemsArray != nil) {
            for item in itemsArray! {

            let thisitem = item as! NSDictionary
            print(thisitem.object(forKey: "message") as? String)
            print(thisitem.object(forKey:"created_time") as? String)
            let title1 = thisitem.object(forKey: "message") as? String
            let value1=thisitem.object(forKey:"created_time") as? String
            if(title1 != nil && value1 != nil) {
                  let news = FacebookPost(title: title1!, value: value1!)
                    self.posts.append(news)
                }

            }}

        }
    }
 do_table_refresh()
}

func do_table_refresh() {


DispatchQueue.global(qos: .background).async {

DispatchQueue.main.async {
self.table.reloadData()
}
}
}
func loadSampleNews() {
    let news1 = FacebookPost(title: "ich bin ein datum", value: "Ich bin eine news")

    let news2 = FacebookPost(title: "ich bin ein datum2", value: "Ich bin eine news2")

    let news3 = FacebookPost(title: "ich bin ein datum3", value: "Ich bin eine news3")

    posts += [news1, news2, news3]
}

override func numberOfSections(in: UITableView) -> Int {
    return 1
}
override func tableView(_: UITableView, numberOfRowsInSection section: Int) -> Int {
    return posts.count
}
override func tableView(_: UITableView, cellForRowAt: IndexPath) -> UITableViewCell {
    let cellIdentifier = "NewsTableViewCell"
    let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: cellForRowAt as IndexPath) as! NewsTableViewCell

    let news = posts[cellForRowAt.row]

    cell.date.text = news.title
    cell.news_text.text = news.value

    return cell
}
}

The loadSampeNews() works perfectly, but pullFacebookNews() does not populate the table. While debugging the array is filled..


Solution

  • If you set breakpoints, you will see that do_table_refresh() gets called before you hit if let responsejson = response.result.value. This is because the Alamofire call has a completion handler. You have to wait until the internet call is complete before you call do_table_refresh().

    So you essentially just have to move do_table_refresh() if all of your data is loading correctly like you say it is.

    func pullFacebookNews() -> Void {
      let params = ["limit":"100", "access_token": myaccesstoken]
      Alamofire.request( "https://graph.facebook.com/<page-id>/posts", parameters: params).responseJSON{ response in
    
        if let responsejson = response.result.value {
          let JSON = responsejson as! NSDictionary
          let itemsArray: NSArray? = JSON.object(forKey: "data") as? NSArray
    
          if(itemsArray != nil) {
            for item in itemsArray! {
              let thisitem = item as! NSDictionary
              print(thisitem.object(forKey: "message") as? String)
              print(thisitem.object(forKey:"created_time") as? String)
              let title1 = thisitem.object(forKey: "message") as? String
              let value1=thisitem.object(forKey:"created_time") as? String
              if(title1 != nil && value1 != nil) {
                let news = FacebookPost(title: title1!, value: value1!)
                self.posts.append(news)
              }
            }
          }
          self.do_table_refresh()
        }
      }
    }
    

    Additionally, don't name your methods with that syntax. It is not best practice. Should be doTableRefresh() or something.