tableView data source empty in viewDidLoad() – Swift

Below is my ViewController code. The println in GetRequest prints the correct data that it receives from the HTTP GET request. At this point, tableData has 10 key-value pairs. However, if I put a break point after the call to GetRequest() in viewDidLoad(), tableData is empty and nothing is displayed in the tableView. Why is this? Where am I going wrong?

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
{
    @IBOutlet var tableView: UITableView!
    var tableData: [String:String] = [:]
    let textCellIdentifier = "TextCell"

func GetRequest(urlPath: String)
{
    var LatestWaitTimes: [String:String] = [:]
    let url: NSURL = NSURL(string: urlPath)!
    let session = NSURLSession.sharedSession()
    let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in

        if error != nil {
            // If there is an error in the web request, print it to the console
            println(error.localizedDescription)
        }

        var err: NSError?
        var jsonResult: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err)
        if err != nil {
            // If there is an error parsing JSON, print it to the console
            println("JSON Error \(err!.localizedDescription)")
        }

        let json = JSON(jsonResult!)
        let count: Int? = json.array?.count

        if let ct = count {
            for index in 0...ct-1 {
                let name = json[index]["CrossingName"].string
                var wait = json[index]["WaitTime"].stringValue
                if (wait == "-1")
                {
                    wait = "No Info"
                }
                else
                {
                    wait += " min"
                }
                println(name!+": "+wait)
                LatestWaitTimes[json[index]["CrossingName"].stringValue] = wait as String?
            }
        }
        self.tableData = LatestWaitTimes
    })
    task.resume()
}

override func viewDidLoad() {
    super.viewDidLoad()
    var apiInfo = GetWaitTimes()
    GetRequest(apiInfo.BorderCrossingApi+"?AccessCode="+apiInfo.AccessCode)
    self.tableView.delegate = self
    self.tableView.dataSource = self
    tableView.reloadData()
}

func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1;
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return tableData.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    var cell = tableView.dequeueReusableCellWithIdentifier(self.textCellIdentifier) as! UITableViewCell
    let thisEntry = self.tableData.values.array[indexPath.row]
    cell.textLabel?.text = thisEntry+": "+tableData[thisEntry]!
    return cell
}

func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}

  • Can I upload my application utilizing WatchKit to the App Store now?
  • iOS: NSString loses URL, (null) is shown
  • iOS 7 Weather app expand/collapse transition
  • How do I call a webservice in Swift?
  • Swift spritekit set userdata
  • heightForRowAtIndexPath being called for all rows & how many rows in a UITableView before performance issues?
  • 3 Solutions Collect From Internet About “tableView data source empty in viewDidLoad() – Swift”

    The problem is that GetRequest runs asynchronously. So you have to reloadData inside the completionHandler of dataTaskWithURL:

    let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
    
        // do all of your existing stuff here
    
        dispatch_async(dispatch_get_main_queue()) {
            self.tableData = LatestWaitTimes
            self.tableView.reloadData()
        }
    })
    task.resume()
    

    You can remove the reloadData from within viewDidLoad.

    Rearrange the orders of the method calls:

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.delegate = self
        self.tableView.dataSource = self
        var apiInfo = GetWaitTimes()
        GetRequest(apiInfo.BorderCrossingApi+"?AccessCode="+apiInfo.AccessCode)
        tableView.reloadData()
    }
    

    Explanation: you set the delegate and dataSource before you GetRequest() so the dataSource won’t be nil.

    Try this it may help you

    you can add a callback (for reload tablview) in GetRequest function and run the callback after parser json in completionHandler

    Maybe When you set the delegate with tableview, tableData still be nil (waitting for http response)

    this is my code .you can refer to

    demand.loadDataFromServer(self.view, done: { () -> Void in
         self.demands = demand.getDemandDataList()
         dispatch_async(dispatch_get_main_queue(), { () -> Void in
             self.tableView.reloadData()
         })
    })
    
    
    func loadDataFromServer(view:UIView,done:(() -> Void)!){
        var request:HttpRequest = HttpRequest(view:view)
        request.GET(getDemandListURL, parameters: nil, success: { (dict) -> Void in
            self.demandLists = dict["data"] as NSMutableArray
            done()
            }, failed: { (dict) -> Void in
    
            }) { (error) -> Void in
        }
    }