How do I refresh a tableview?

I dare to write here to see if you can help me with a detail that I have when making a query and download an arrangement that can have changes, in short, when making a new record I would like A new query is made to my API to download the new data. I appreciate all comments, thank you very much, greetings to all.

For this I use Model and Protocol.

CitasDetalles.swift

import UIKit

class DetallesCitas: NSObject {

var idCitaCliente: String?
var nombreCitaCliente: String?
var idClienteCita: String?
var horarioCita: String?
var fechaCita: String?
var citaStatus: String?
var citaServicio: String?
var citaBarbero: String?

override init(){

}

init(idCitaCliente: String, nombreCitaCliente: String, idClienteCita:String, horarioCita:String, fechaCita: String, citaStatus: String, citaServicio: String, citaBarbero: String) {

    self.idCitaCliente = idCitaCliente
    self.nombreCitaCliente = nombreCitaCliente
    self.idClienteCita = idClienteCita
    self.horarioCita = horarioCita
    self.fechaCita = fechaCita
    self.citaStatus = citaStatus
    self.citaBarbero = citaBarbero

}

override var description: String{

    return "idCitaCliente: \(idCitaCliente), nombreCitaCliente: \(nombreCitaCliente), idClienteCita: \(idClienteCita), horarioCita: \(horarioCita), fechaCita: \(fechaCita), citaStatus: \(citaStatus), citaServicio: \(citaServicio), citaBarbero: \(citaBarbero)"
}
}

CitasModelo.swift

import UIKit
protocol CitasModeloProtocol: class {

func itemsCitas(lasCitas: NSArray)
}

let idCliente: String = UserDefaults.standard.string(forKey: “id”)!

class CitasModelo: NSObject {

weak var elDelegado: CitasModeloProtocol!

let urlPath = "http://sistema.gents.mx/movilBackendGENTS/listaCitasCliente.php?idCliente=\(idCliente)"

func downloadItems(){

    let url: URL = URL(string: urlPath)!
    let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)
    let task = defaultSession.dataTask(with: url){
        (data, response, error) in
        if error != nil{

            print("Error al descargas las citas")

        }else{

            print("Datos descargados")

            self.parseJSON(data!)


        }
    }

    task.resume()

}



func parseJSON(_ data:Data){

    var resultFromServer: Any?
    resultFromServer = try? JSONSerialization.jsonObject(with: data, options: [])

    if let respdict = resultFromServer as? [String : Any] {
        //respone in dictionary format

        var jsonDi = NSDictionary()

        do{

            jsonDi = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as! NSDictionary

            let parsedJSON = jsonDi
            if parsedJSON["status"] as! String == "401"{

                print(parsedJSON["message"] as! String)

            }

        } catch {


        }



    }

    else if let respArr = resultFromServer as? [Any]{
        //response is array type
            var jsonResult = NSArray()
        do{

            jsonResult = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as! NSArray

        } catch let error as NSError {

            print(error)
        }

        var jsonElement = NSDictionary()
        let detalles = NSMutableArray()
        for i in 0 ..< jsonResult.count{

            jsonElement = jsonResult[i] as! NSDictionary
            let detalle = DetallesCitas()

            let idCitaCliente = jsonElement["id"]
            let nombreCitaCliente = jsonElement["usuarioCita"]
            let idClienteCita = jsonElement["idCliente"]
            let horarioCita = jsonElement["citaHorario"]
            let fechaCita = jsonElement["citaDia"]
            let citaStatus = jsonElement["statusCitas"]
            let citaServicio = jsonElement["citaServicio"]
            let citaBarbero = jsonElement["barberoCita"]

            detalle.idCitaCliente = idCitaCliente as? String
            detalle.nombreCitaCliente = nombreCitaCliente as? String
            detalle.idClienteCita = idClienteCita as? String
            detalle.horarioCita = horarioCita as? String
            detalle.fechaCita = fechaCita as? String
            detalle.citaStatus = citaStatus as? String
            detalle.citaServicio = citaServicio as? String
            detalle.citaBarbero = citaBarbero as? String

            detalles.add(detalle)

        }

        DispatchQueue.main.async(execute: { ()-> Void in

            self.elDelegado.itemsCitas(lasCitas: detalles)
        })

    }

    else if let stringRespt = String(data: data, encoding: .utf8){
        //resp is string
    }


}
}

ListaCitasVC.swift

import UIKit

class ListaCitasVC: UIViewController, UITableViewDataSource, UITableViewDelegate, CitasModeloProtocol {

var feedItems: NSArray = NSArray()
var selectCita : DetallesCitas = DetallesCitas()

@IBOutlet weak var citasLista: UITableView!

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    citasLista.reloadData()
}

override func viewDidLoad() {
    super.viewDidLoad()

    self.citasLista.delegate = self
    self.citasLista.dataSource = self

    let citasModelo = CitasModelo()
    citasModelo.elDelegado = self
    citasModelo.downloadItems()
    self.citasLista.reloadData()
    // Do any additional setup after loading the view.
}

func itemsCitas(lasCitas: NSArray) {
    feedItems = lasCitas
    self.citasLista.reloadData()
}

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

Hi @rockyto,
I am not sure what the problem is. Are you looking for comments on the code or do you want help fixing something?

cheers,

Call downloadItems() again when you need to refresh the data.

Hello, I appreciate your response and having read the code. In this app there is a form to create appointments and when the user fills out the form and the information is sent to the server to view that record in the uitableview, when making the whole record and go to the tableview where the registered appointments are stored the tableview does not sample, you would have to uninstall the application and reinstall it so that the application does the whole process of downloading the data from the server, if I close and open the app it does not function to download the data. Thanks greetings.

Hi @rockyto,
ok. Your datasource is created and data loaded in the viewDidLoad method of listaCitasVC. This is in the form of the class citasModelo.

When you use reloadModel, you are only refreshing the tableview, and your data source is still the same. If you want to reload the datasource, then you need to reload the data in the datasource, I believe that is done by using the downloadItems again. However when you are adding the data from another form, you can trigger the downloadItems to update the datasource.

cheers,

1 Like

For example, if I have only one record in the database and I make the query, it returns that same record, if I add more records and return to the tableview without closing the app, the other records I made are not displayed, and only shown the result and is the same as the first query, it is as if it was only executed once since opening the application and saves that same result without executing again.

In my class where the table is displayed I have this to call the class that downloads the data from the server:

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

    let citasModelo = CitasModelo()
    citasModelo.elDelegado = self
    citasModelo.downloadItems()
    self.citasLista.reloadData()
   
}

But I got this error:
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

2019-08-18 19:41:56.756279-0500 Gents[12112:322573] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

And in my class CitasModelo.swift Xcode marks the error in self.elDelegado…:

        DispatchQueue.main.async(execute: { ()-> Void in
            
            **self.elDelegado.itemsCitas(lasCitas: detalles)**
        })

hi @rockyto,
I was expecting this error to happen. This is because you are reloading the tables immediately after downloadItems. You would want to run this at the end of the parsing json, because it is then where the data is loaded/set.

cheers,

1 Like

I don’t know how, but I’ll try, thanks.

One way to do it would be to add a parameter to your downloadItems method. Right now, you’re simply saying “Download these items”. By adding a parameter that would be a completionHandler, you would be saying “Download these items and then when you’re finished, do this thing next”. Then make sure to call that completion handler inside of defaultSession.dataTask(with:). In fact, that’s exactly what you have between the { and the } after that method! Your print statement happens only after dataTask goes and does a URL request. Everything in that completion handler is something that you are giving to the dataTask and saying, “Please do all of this stuff whenever you finish making this URL request. If you get a data, response, or error object, I want you to do the following with them”.

Here’s a good example of how to create a completion handler. Good luck!

1 Like

Hi, thanks for your response, he managed to move forward with the correction by replacing the line
let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)

for this one:
Foundation.URLSession(configuration: URLSessionConfiguration.ephemeral)

And finally adding this other line:
URLCache.shared.removeAllCachedResponses()

Being that way:

let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.ephemeral)
        URLCache.shared.removeAllCachedResponses()
        let task = defaultSession.dataTask(with: url){
            (data, response, error) in

This topic was automatically closed after 166 days. New replies are no longer allowed.