Search code examples
iosuitableviewswiftreloaddata

Table not reloading in another TabBar ViewController


I'm using a TabBar Controller with 2 tabs - Bills Reminder, Bills Paid.

After setting the status of the records in Bills Reminder, and I went into Bills Paid tab, it isn't showing the bills that have been marked as paid.

I quit the app and relaunch it , then went into Bills Paid tab and it is displaying all the bills that has been paid correctly now.

I'm using viewWillAppear in my Bills Paid View controller.

BillsPaidTableViewController.swift

class BillsPaidTableViewController: UITableViewController, NSFetchedResultsControllerDelegate  {

    var fetchResultController:NSFetchedResultsController!

    override func viewWillAppear(animated: Bool) {
        println("Hey I'm loading bills paid")

        self.tableView.reloadData()
        super.viewWillAppear(false);

        self.tableView.tableFooterView = UIView(frame: CGRectZero)
    }

    /*
    comments: viewDidLoad will only load once and will not load after subsequent tapping on the the tab

    override func viewDidLoad() {
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations

        self.tableView.tableFooterView = UIView(frame: CGRectZero)
    }*/ 

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

    // MARK: - Table view data source

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Potentially incomplete method implementation.
        // Return the number of sections.
        return self.fetchedResultsController.sections?.count ?? 0

    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete method implementation.
        // Return the number of rows in the section.
        let sectionInfo = self.fetchedResultsController.sections![section] as! NSFetchedResultsSectionInfo
        return sectionInfo.numberOfObjects

    }


    var fetchedResultsController: NSFetchedResultsController {
        if _fetchedResultsController != nil {
            return _fetchedResultsController!
        }

        let fetchRequest = NSFetchRequest()
        // Edit the entity name as appropriate.
        if let managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext {
            let entity = NSEntityDescription.entityForName("Bills", inManagedObjectContext: managedObjectContext)
            fetchRequest.entity = entity

            // Set the batch size to a suitable number.
            fetchRequest.fetchBatchSize = 20

            // Edit the sort key as appropriate.

            let predicate = NSPredicate(format: " paid == 1 ")
            fetchRequest.predicate = predicate

            // Edit the section name key path and cache name if appropriate.
            // nil for section name key path means "no sections".
            let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
            aFetchedResultsController.delegate = self
            _fetchedResultsController = aFetchedResultsController

            var error: NSError? = nil
            if !_fetchedResultsController!.performFetch(&error) {
                // Replace this implementation with code to handle the error appropriately.
                // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                //println("Unresolved error \(error), \(error.userInfo)")
                abort()

            }
        }

        return _fetchedResultsController!
    }

    var _fetchedResultsController: NSFetchedResultsController? = nil

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("BillPaidCell", forIndexPath: indexPath) as! BillPaidTableViewCell

        // Configure the cell...
        self.configureCell(cell, atIndexPath: indexPath)

        return cell
    }

    func configureCell(cell: BillPaidCell, atIndexPath indexPath: NSIndexPath) {

        let object = self.fetchedResultsController.objectAtIndexPath(indexPath) as! NSManagedObject

        cell.billName?.text = object.valueForKey("name")!.description
        cell.billAmt?.text = convertToDecimal( (object.valueForKey("amount")!.description as NSString).doubleValue , 2, 2)
        cell.dateDue?.text = object.valueForKey("date_due")!.description
        cell.datePaid?.text = object.valueForKey("date_paid")!.description

    }
}

Each time, I click on the Bills Paid tab, it will show the message "Hey I'm loading bills paid", no problem with this part. However, the table isn't loading although I'm using .reloadData().

Where did I go wrong with this part?


Solution

  • You should refetch data when click on paid tab. To do this you can simply add _fetchedResultsController = nil in viewWillAppear function before calling table reloadData.