0

In my app I have a ViewController with a collectionView and a tableView. My CollectionView shows the dates and the tableView shows the data in that date.

I need to create a date before create the other datas, so when I type in the date it shows up a alert and them we go to other view to Create a new data.

The problem is that when I save a new data and I use a popViewController to go back my previous view my tableView does not reload data.

I can see the saved data when I back the view again and so I return to the view

I've tried to use the myTableView.reloadData() in ViewWillAppear, but it didn't work.

How can I reload myTableView as soon as return the view?

Here is a link to the app video. Here is the app working

Here is my IBAction to save data:

@IBAction func btSaveNewMeasures(_ sender: UIBarButtonItem) {

    let allMeasures = NSEntityDescription.entity(forEntityName: "AllMeasures", in: context)

    for textField in tfMeasuresValues {

        let newMeasure = NSManagedObject(entity: allMeasures!, insertInto: context)

        if let valueTxt = textField.text {
            let value = convertNumber.convertToDouble(valueTxt)
            if value != 0 {

                switch textField.tag {
                case 1: ///Body Measures
                    //Peso
                    let type = MeasuresType.bodyMeasures.rawValue
                    let index = NSNumber(value: textField.tag).int64Value
                    self.saveNewMessure(newMeasure, type: type, title: "Peso", value: value, index: index)
                case 2:
                    //Altura
                    let type = MeasuresType.bodyMeasures.rawValue
                    let index = NSNumber(value: textField.tag).int64Value
                    self.saveNewMessure(newMeasure, type: type, title: "Altura", value: value, index: index)
                case 3:
                    //%Gordura
                    let type = MeasuresType.bodyMeasures.rawValue
                    let index = NSNumber(value: textField.tag).int64Value
                    self.saveNewMessure(newMeasure, type: type, title: "% Gordura", value: value, index: index)
                default:
                    break
                }
            }
        }
    }
    do {
        try context.save()

        guard let navigation = navigationController else {return}
        navigation.popViewController(animated: true)

        self.delegate?.didFinishUpdates(finished: true)

    } catch let error {
        print("Error Saving Measures Values: \(error)")
    }
}

}

This is my cellForRowAt:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: MeasureCell.identifier, for: indexPath) as! MeasureCell
    let measures = fetchedRCAllMeasuresByDay.object(at: indexPath)
    cell.setupMeasureCell(measure: measures)
    return cell
}

I've checked if myTableView.reloadData() has been called in viewWillApperar and I confirmed that.

Here are my methods setupTableView and setupCollectionView in my class MeasureController:

private func setupTableView() {
    myTableView.backgroundColor = Theme.background
    myTableView.separatorStyle = .none
    myTableView.tableFooterView = UIView()
    myTableView.delegate = self
    myTableView.dataSource = self
    myTableView.rowHeight = UITableView.automaticDimension
    myTableView.estimatedRowHeight = 80
    myTableView.register(MeasureCell.nib, forCellReuseIdentifier: MeasureCell.identifier)
}

private func setupCollectionView() {
    myCollectionView.backgroundColor = Theme.background
    myCollectionView.delegate = self
    myCollectionView.dataSource = self        
    myCollectionView.register(UINib(nibName: "DateCollectionCell", bundle: nil), forCellWithReuseIdentifier: cellCollectionViewID)

    //Set Collection View Cell Aligment
    let alignedFlowLayout = AlignedCollectionViewFlowLayout(horizontalAlignment: .right, verticalAlignment: .top)
    alignedFlowLayout.scrollDirection = .horizontal
    myCollectionView.collectionViewLayout = alignedFlowLayout
}

enter image description here

==============================================

This is my NSFetechedResultsControllerDelegate fixed:

extension MeasureController: NSFetchedResultsControllerDelegate {

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
    switch type {
    case .insert:
        myTableView.insertSections(IndexSet(integer: sectionIndex), with: .fade)
    case .delete:
        myTableView.deleteSections(IndexSet(integer: sectionIndex), with: .fade)
    case .move:
        break
    case .update:
        myTableView.reloadSections(IndexSet(integer: sectionIndex), with: .fade)
    @unknown default:
        fatalError()
    }
}


func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    myTableView.reloadData()
    myCollectionView.reloadData()
}

//Allow to show full section name in header.
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, sectionIndexTitleForSectionName sectionName: String) -> String? {
    return sectionName
}

}

And here is the link for the video with the new app behaviour, after fixed the NSFRCD.

New App Behaviour

I found that cellForRowAt is not called after new data is added as soon as old data is deleted. Although numberOfSections has been called, the value is zero. But if you go back to the previous view and re-enter MeasureView, numberOfSections will have a correct value, in other words, numberOfSections will be nonzero.

I've tried to use delegates and callbacks to reload myTableView but I didn't success.

Afonso
  • 87
  • 2
  • 9
  • 1
    “I’ve tried ... myTableView.reloadData() in viewWillAppear, but it didn't work” ... So, what did it do? Add logging statements or breakpoints and figure out whether (a) `viewWillAppear` was or wasn’t called; or (b) whether your `cellForRowAt` was or wasn’t called; or (c) it was called but your data source methods were not returning different results (i.e. you model didn’t change). This just calls for rolling up your sleeves and figuring out where it failed through judicious logging statements and/or breakpoints. But there’s nowhere close to enough information here to diagnose what’s going on. – Rob Sep 02 '19 at 03:39
  • `myTableView.reloadData()` must be the last statement in `viewWillApperar`, because you need to reload table after setting up all datasource. – Rocky Sep 02 '19 at 10:21
  • Hi Rob, I verified that viewWillAppear is working correctly. It calls myTableView.reloadData () and I've checked the cellForRowAt. In the last one I found that it is called only when the view first appears, but when we return to it using popViewController in the data addition view cellForRowAt is not called, although myTableView.reloadData () in viewWillAppear () is called. What's going on? I'm lost. – Afonso Sep 02 '19 at 10:28
  • Hi Rocky, I put the myTableView.reloadData() as the last statement, but the result was the same. – Afonso Sep 02 '19 at 10:31
  • It's so weird. When I go back to the view the myTableView.reloadData() is called, but the tableView Delegate and DataSource are not called. They are only called if I back to the previous views and access it again. I'm totally lost. – Afonso Sep 02 '19 at 15:48
  • Hi guys, I was able to solve part of the problem by fixing my NSFetchedResultsControllerDelegate (check the code above). So now, when I add the new measurements, they appear in the view as they are added. But a problem still remains. If I need to delete them after they appeared and I add new measures they don’t appear and I have to back the previous view and access to MeasureView again to see the measures added (check the new link with that new situation). What's going on? – Afonso Sep 08 '19 at 14:48
  • I found that cellForRowAt is not called after new data is added as soon as old data is deleted. Although numberOfSections has been called, the value is zero. But if you go back to the previous view and re-enter MeasureView, numberOfSections will have a correct value, in other words, numberOfSections will be nonzero. – Afonso Sep 09 '19 at 23:42
  • Hi guys, I still couldn't fix the issue. I've figured out the issue is in my fetchedResultsController or in its delegate. I don't know I the preblem is that I have a tableView and a conllectionView in the same viewcontroller with only one extension with NSFetchedResultsControllers for both. I'm trying new approach in my code and if I got success I let you know. – Afonso Sep 10 '19 at 16:21

0 Answers0