LizG
LizG

Reputation: 2530

TableViewController not updating cells

This app allows Rider to request a ride and driver to accept the request. In this tableview are the rides the riders (2) have requested.

Unable to update tableviewcells.

import UIKit
import Firebase
import FirebaseDatabase
import FirebaseAuth
import FirebaseCore
import CoreLocation

class RequestsTVC: UITableViewController {

var geoCoder : CLGeocoder?

var rideRequests = [FIRDataSnapshot]()
let ref = FIRDatabase.database().reference() //(withPath: "RideRequests")

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self

    self.geoCoder = CLGeocoder()

    self.navigationController?.isNavigationBarHidden = false

    /*
     .observe is called whenever anything changes in the Firebase -
     It's also called here in viewDidLoad().
     It's always listening.

     */

    ref.child("drivers").child("RideRequests").observe(FIRDataEventType.value, with: { snapshot in
        self.rideRequests.removeAll()
        for item in snapshot.children{
            self.rideRequests.append(item as! FIRDataSnapshot)
        }
        self.rideRequests.reverse()
        self.tableView.reloadData()
    })

    DispatchQueue.main.async (execute: { () -> Void in
        self.tableView.reloadData()
    })

} // func viewDidLoad()


override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(true)


}


// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {

    return 1
}


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return rideRequests.count
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "RequestsCell", for: indexPath)

    let usernameLabel = cell.contentView.viewWithTag(2) as! UILabel
    let locationLbl = cell.contentView.viewWithTag(1) as! UILabel
    let destinationLbl = cell.contentView.viewWithTag(3) as! UILabel

    let request = self.rideRequests[indexPath.row]

    let username = request.childSnapshot(forPath: "username")

    let destLatString = request.childSnapshot(forPath: "destLat").value
    let destLat = Double(destLatString as! String)

    let destLongString = request.childSnapshot(forPath: "destLong").value
    let destLong = Double(destLongString as! String)


    let usernameText = username.value as! String


    let location = RiderVC.instance.locationManager.location
    let destination = CLLocation(latitude: destLat!, longitude: destLong!)


    usernameLabel.text = usernameText

    locationLbl.text = "Waiting ..."
    destinationLbl.text = "Loading ... "

    // LOCATION and DESTINATION


    geoCoder?.reverseGeocodeLocation(location!, completionHandler: { (data, error) -> Void in
        guard let placeMarks = data as [CLPlacemark]! else {
            return
        }

        let loc: CLPlacemark = placeMarks[0]
        let addressDict : [NSString: NSObject] = loc.addressDictionary as! [NSString: NSObject]
        let addrList = addressDict["FormattedAddressLines"] as! [String]
        print(addrList)
        locationLbl.text = addrList[0]

        // THAT'S THE FIRST BIT DONE
        // THIS IS STILL INSIDE THE COMPELTION HANDLER

        // NOW DO DESTINATION
        // DESTINATION


        self.geoCoder?.reverseGeocodeLocation(destination, completionHandler: { (data, error) -> Void in

            guard let placeMarks = data as [CLPlacemark]! else {
                return
            }

            let loc: CLPlacemark = placeMarks[0]
            let addressDict : [NSString: NSObject] = loc.addressDictionary as! [NSString: NSObject]
            let addrList = addressDict["FormattedAddressLines"] as! [String]
            destinationLbl.text = addrList[0]
        })

    })

    return cell
}

**Screen shot of table view not updating after 1st cell **

enter image description here

Upvotes: 0

Views: 291

Answers (2)

Ethan
Ethan

Reputation: 471

make sure you reload tableview in main queue in with parameter closure.

ref.child("drivers").child("RideRequests").observe(FIRDataEventType.value, with: { snapshot in
    self.rideRequests.removeAll()
    for item in snapshot.children{
        self.rideRequests.append(item as! FIRDataSnapshot)
    }
    self.rideRequests.reverse()
    DispatchQueue.main.async (execute: { () -> Void in
        self.tableView.reloadData()
    })
})

Upvotes: 1

Dale
Dale

Reputation: 3323

The callbacks from Geocoder are asynchronous and you can't simply change the values in the table cells by updating the label values inside the callback - you have to inform the table view to reload the cell in order to update it.

So, you need to pull out the GeoCoder lookups from inside tableView:cellForRowAt and move them into a loop in either viewDidLoad or viewWillAppear. The final values should form part of you model.

Inside the callbacks for the GeoCoder you would then tell the table view to reload each individual cell calling tableView.reloadRows with a single value array.

Upvotes: 0

Related Questions