How to retain updated data in UITableView when back button is Tapped

I am creating an Event App, wherein the list of participants fetch from API are listed in an UITableView. When the user tapped the checkInOutbutton its either, it will check in and register for the event or check out after the event. In every after the user checkin or checkout from the event, the user should pull to refresh to update the data inside the table. I used the codes below to update the data.

var refresher: UIRefreshControl!

 override func viewDidLoad() {
    super.viewDidLoad()

  refresher = UIRefreshControl()
    refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
    refresher.addTarget(self, action: #selector(ParticipantsViewController.refresh), for: UIControlEvents.valueChanged)
    ParticipantTableView.addSubview(refresher)


}

//MARK: FUNCTIONS

@objc func refresh() {

    refresher.endRefreshing()
    getParticipants()
    ParticipantTableView.reloadData()
     _ = SCLAlertView(appearance: Appearance).showSuccess("Success", subTitle: "Participants Updated!")
}

I successfully updated the table once I used pull to refresh. The issue is, when I tapped the back button going to my dashboard and tapped the button going back to the VC of my UItableview which is participantViewController, the data is not updated. It goes back to its original data. How can I retain the updated data even if I tapped the back button and goes back to theparticipantsorregistered participants` VC?. Hope you can help me.

original data, gray bgcolor and NOT REGISTERED label(checkin and checkout button is inside the folding cell

original data, gray bgcolor and NOT REGISTERED label(checkin and checkout button is inside the folding cell).

data once the user tapped checkin button, the background colour turned to green and label is REGISTERED

data once the user tapped checkin button, the background colour turned to green and label is REGISTERED

Dashboard when back button is tapped

Dashboard when back button is tapped

Back button when tapped

 @IBAction func backbutton(_ sender: UIButton) {
     self.dismiss(animated: true, completion: nil)
}

ParticipantViewController

import UIKit
import FoldingCell
import SCLAlertView
import AASquaresLoading

class ParticipantsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var ParticipantTableView: UITableView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var countLabel: UILabel!
@IBOutlet weak var notifImageView: UIImageView!

var refresher: UIRefreshControl!

var validPincode: String!
var titleString: String!

var participants: [Attendee]!
var filteredParticipants = [Attendee]()


let kCloseCellHeight: CGFloat = 122
let kOpenCellHeight: CGFloat = 475

var cellHeights = [CGFloat]()

let searchController = UISearchController(searchResultsController: nil)


override func viewDidLoad() {
    super.viewDidLoad()

    createCellHeightsArray()
    configureSearchBar()
    configureAALoading()
    countNotif()

    titleLabel.text = self.titleString

    refresher = UIRefreshControl()
    refresher.attributedTitle = NSAttributedString(string: "Pull to refresh")
    refresher.addTarget(self, action: #selector(ParticipantsViewController.refresh), for: UIControlEvents.valueChanged)
    ParticipantTableView.addSubview(refresher)


}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


override func viewDidAppear(_ animated: Bool) {
    self.ParticipantTableView.reloadData()
}



@IBAction func backbutton(_ sender: UIButton) {
     self.dismiss(animated: true, completion: nil)
}



//MARK: FUNCTIONS

@objc func refresh() {

    refresher.endRefreshing()
    getParticipants()
    ParticipantTableView.reloadData()
     _ = SCLAlertView(appearance: Appearance).showSuccess("Success", subTitle: "Participants Updated!")


}


func configureAALoading() {
    self.view.squareLoading.color = UIColor(red: 80/255.0, green: 187/255.0, blue: 113/255.0, alpha: 1.0)
    self.view.squareLoading.backgroundColor = UIColor(red: 0/255.0, green: 0/255.0, blue: 0/255.0, alpha: 0.7)
}

func getParticipants() {

    var participantType: ParticipantType!

    if self.titleString == "PARTICIPANTS" {
        participantType = .all
    }else {
        participantType = .active
    }

    self.view.squareLoading.start(0.0)

    let api = APIService()

    api.getParticipants(enteredPincode: validPincode, participantType: participantType, successBlock: { (attendees) in

         self.participants = attendees
        self.view.squareLoading.stop(0.0)

        if self.searchController.isActive && self.searchController.searchBar.text != "" {
            self.filterContentForSearchText(searchText: self.searchController.searchBar.text!)
        }else {
            self.ParticipantTableView.reloadData()
        }



    }) { (error) in
        // Hide loading view
        self.view.squareLoading.stop(0.0)
        _ = SCLAlertView(appearance: Appearance).showError("Network Error", subTitle: "\(error)")

    }


}



func countNotif(){

    if participants.count == 0 {
        countLabel.isHidden = true
        notifImageView.isHidden = true

    }else {
        countLabel.text = "\(participants.count)"
        notifImageView.image = #imageLiteral(resourceName: "participant_notif")
    }
}


  func createCellHeightsArray() {

    cellHeights.removeAll()

    if searchController.isActive && searchController.searchBar.text != "" {
        for _ in 0...filteredParticipants.count {
            cellHeights.append(kCloseCellHeight)
        }
    }else {
        for _ in 0...participants.count {
            cellHeights.append(kCloseCellHeight)
        }
    }
}


    func filterContentForSearchText(searchText: String, scope: String = "All") {
        filteredParticipants = participants.filter { participants in
            return participants.displayName.lowercased().contains(searchText.lowercased()) || (participants.department.lowercased().contains(searchText.lowercased()))
            //                || (participants.employeeNumber?.contains(searchText))! ||
        }

        createCellHeightsArray()
        ParticipantTableView.reloadData()

    }

func configureSearchBar() {

    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false
    definesPresentationContext = true

    searchController.searchBar.textColor = UIColor.white
    searchController.searchBar.placeholder = "Search by name, department, and employee number"
    searchController.searchBar.searchBarStyle = .minimal
    searchController.searchBar.barTintColor = UIColor(red: 26/255.0, green: 99/255, blue: 42/255, alpha: 1.0)
    searchController.searchBar.tintColor = UIColor.white
    searchController.searchBar.backgroundColor = UIColor(red: 26/255.0, green: 99/255, blue: 42/255, alpha: 1.0)

    searchController.searchBar.isTranslucent = false

    self.ParticipantTableView.tableHeaderView = searchController.searchBar
}



// MARK: TABLE VIEW DATA SOURCE



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

    if searchController.isActive && searchController.searchBar.text != "" {
        return filteredParticipants.count
    }
    //print(participants.count)
    return (participants.count)
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "FoldingCell", for: indexPath)
           return cell
}

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

    guard case let cell as ParticipantCell = cell else {
        return
    }

    cell.backgroundColor = UIColor.clear

    if searchController.isActive && searchController.searchBar.text != "" {
        cell.participant = filteredParticipants[indexPath.row]
    }else {
        cell.participant = participants[indexPath.row]
    }

    if cellHeights[(indexPath as NSIndexPath).row] == kCloseCellHeight {
        cell.unfold(false, animated: false, completion: nil)
    } else {
        cell.unfold(true, animated: false, completion: nil)
    }
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return cellHeights[(indexPath as NSIndexPath).row]
}

// MARK: TABLE VIEW DELEGATE

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    let cell = tableView.cellForRow(at: indexPath) as! FoldingCell

    if cell.isAnimating() {
        return
    }

    var duration = 0.0

    if cellHeights[(indexPath as NSIndexPath).row] == kCloseCellHeight { // open cell
        cellHeights[(indexPath as NSIndexPath).row] = kOpenCellHeight
        cell.unfold(true, animated: true, completion: nil)
        duration = 0.3
    } else {// close cell
        cellHeights[(indexPath as NSIndexPath).row] = kCloseCellHeight
        cell.unfold(false, animated: true, completion: nil)
        duration = 0.5
    }

    UIView.animate(withDuration: duration, delay: 0, options: .curveEaseOut, animations: { () -> Void in
        tableView.beginUpdates()
        tableView.endUpdates()
    }, completion: nil)

    }

}

extension ParticipantsViewController: UISearchResultsUpdating {
func updateSearchResults(for searchController: UISearchController) {
    filterContentForSearchText(searchText: searchController.searchBar.text!)
    }
}

extension UISearchBar {

var textColor: UIColor? {
    get {
        if let textField = self.value(forKey: "searchField") as? UITextField {
            return textField.textColor
        }else {
            return nil
        }
    }

    set (newValue) {
        if let textField = self.value(forKey: "searchField") as? UITextField {
            textField.textColor = newValue
            textField.font = UIFont(name: "HelveticaNeue", size: 20.0)
            }
        }
    }
}

1 answer

  • answered 2018-09-25 02:54 Sam Peters

    Your explanation of the problem is kind of confusing to me but I think I understand what you're saying. My interpretation: You present a the view controller for a tableView and refresh the table view with some new data. Then when you dismiss the view controller and go back to it, the new data is gone and you just see the old data.

    Well if that's your problem, then the solution is pretty simple. When you return to the view controller, you're probably just creating a completely new viewController and presenting it... which isn't gonna have the new data that was fetched from the network.

    In that case you would have to store that original viewController instance in a variable and present THAT, instead of creating an entirely new one.

    Edit:

    somewhere in your code for the dashboard, you probably have this line

    self.present(ParticipantsViewController(), animated: false)
    

    ...or some variant of that. Instead of this, do something along the lines of...

    class DashboardViewController: UIViewController{
    
     var participantsViewController = ParticipantsViewController()
    
        func responseToSomeUserAction(){
            self.present(self.participantsViewController, animated: true)
        }
    
    }
    

    In the code above, the same viewController instance will be presented every time the user wants to display the table view, therefore all the data will still be there.