Xcode的表视图节未更新

问题描述 投票:-1回答:1

我创建了一个新的Xcode 9.4.1主详细项目。我已经编程实现了一个自定义单元格和所有工作正常。我的应用是业余无线电中继器的数据库。我创建的实践应用。我现在想实现一个组由状态中继器条目的多个部分。我的添加/删除功能正常工作从TableView中页。该条目会添加/从正确的部分去除。我把它设置在详细视图进行转发条目更新。问题是,实现代码如下不会改变条目组分组当我改变在详细视图状态然后再返回到主视图。我已经实现了WillAppear作用下self.tableView.reloadData()

这里是我的MasterViewController的代码:

import UIKit
import CoreData

class MasterViewController: UITableViewController, NSFetchedResultsControllerDelegate{

    let cellTableIdentifier = "Cell"

    var detailViewController: DetailViewController? = nil
    var managedObjectContext: NSManagedObjectContext? = nil

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(CustomCell.self,forCellReuseIdentifier: cellTableIdentifier)

        // Do any additional setup after loading the view, typically from a nib.
        navigationItem.leftBarButtonItem = editButtonItem

        let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(insertNewObject(_:)))
        navigationItem.rightBarButtonItem = addButton
        if let split = splitViewController {
            let controllers = split.viewControllers
            detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
        }
    }

    override func viewWillAppear(_ animated: Bool) {
        clearsSelectionOnViewWillAppear = splitViewController!.isCollapsed
        super.viewWillAppear(animated)
        // reload the data into the TableView
        self.tableView.reloadData()
        //self.tableView.reloadSections([1,2,3], with: .none )
    }

    // Adds Repeaters to Table View, saves in Core Data
    @objc
    func insertNewObject(_ sender: Any)
    {
        // create an Alert with a textFields
        let alertController = UIAlertController(title: "Add Repeater",
                                                message: "",
                                                preferredStyle: UIAlertControllerStyle.alert)

        // add the textField to the Alert. Create a closure to handle the configuration
        alertController.addTextField(configurationHandler: {(textField: UITextField!) in
            textField.placeholder="State"
            textField.keyboardType=UIKeyboardType.emailAddress
        })

        // add the textField to the Alert. Create a closure to handle the configuration
        alertController.addTextField(configurationHandler: {(textField: UITextField!) in
            textField.placeholder="County"
            textField.keyboardType=UIKeyboardType.emailAddress
        })

        // add the textField to the Alert. Create a closure to handle the configuration
        alertController.addTextField(configurationHandler: {(textField: UITextField!) in
            textField.placeholder="City"
            textField.keyboardType=UIKeyboardType.emailAddress
        })

        // add the textField to the Alert. Create a closure to handle the configuration
        alertController.addTextField(configurationHandler: {(textField: UITextField!) in
            textField.placeholder="Call Sign"
            textField.keyboardType=UIKeyboardType.emailAddress
        })

        // add the textField to the Alert. Create a closure to handle the configuration
        alertController.addTextField(configurationHandler: {(textField: UITextField!) in
            textField.placeholder="Input Frequency"
            textField.keyboardType=UIKeyboardType.emailAddress
        })

        // add the textField to the Alert. Create a closure to handle the configuration
        alertController.addTextField(configurationHandler: {(textField: UITextField!) in
            textField.placeholder="Output Frequency"
            textField.keyboardType=UIKeyboardType.emailAddress
        })

        // add the textField to the Alert. Create a closure to handle the configuration
        alertController.addTextField(configurationHandler: {(textField: UITextField!) in
            textField.placeholder="Uplink Tone"
            textField.keyboardType=UIKeyboardType.emailAddress
        })

        // add the textField to the Alert. Create a closure to handle the configuration
        alertController.addTextField(configurationHandler: {(textField: UITextField!) in
            textField.placeholder="Downlink Tone"
            textField.keyboardType=UIKeyboardType.emailAddress
        })

        // add the textField to the Alert. Create a closure to handle the configuration
        alertController.addTextField(configurationHandler: {(textField: UITextField!) in
            textField.placeholder="Offset"
            textField.keyboardType=UIKeyboardType.emailAddress
        })

        // add the textField to the Alert. Create a closure to handle the configuration
        alertController.addTextField(configurationHandler: {(textField: UITextField!) in
            textField.placeholder="Use"
            textField.keyboardType=UIKeyboardType.emailAddress
        })

        // create a default action for the Alert
        let defaultAction = UIAlertAction(
            title: "Create",
            style: UIAlertActionStyle.default,
            handler: {(alertAction: UIAlertAction!) in
                // get the input from the alert controller
                let context = self.fetchedResultsController.managedObjectContext
                let newRepeater = Repeaters(context: context)

                newRepeater.state = (alertController.textFields![0]).text!
                newRepeater.county = (alertController.textFields![1]).text!
                newRepeater.location = (alertController.textFields![2]).text!
                newRepeater.call = (alertController.textFields![3]).text!
                newRepeater.input_Freq = (alertController.textFields![4]).text!
                newRepeater.output_Freq = (alertController.textFields![5]).text!
                newRepeater.uplink_Tone = (alertController.textFields![6]).text!
                newRepeater.downlink_Tone = (alertController.textFields![7]).text!
                newRepeater.offset = (alertController.textFields![8]).text!
                newRepeater.use = (alertController.textFields![9]).text!

                // Save the context.
                do {
                    try context.save()
                } catch {
                    let nserror = error as NSError
                    fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
                }

                // reload the data into the TableView
                self.tableView.reloadData()
        })
        // cancel button
        let cancelAction = UIAlertAction(
            title: "Cancel",
            style: UIAlertActionStyle.cancel,
            handler:nil)

        // add the actions to the Alert
        alertController.addAction(defaultAction)
        alertController.addAction(cancelAction)

        // generate test data
        gernerateTestData(alertController: alertController)

        // display the Alert
        present(alertController, animated: true, completion: nil)
    }

    // Creates test data in Alert Controller
    func gernerateTestData(alertController:UIAlertController)
    {
        // increment count
        //count += 1
        // get the textfields and assign test data
        (alertController.textFields![0]).text = "Ohio"
        (alertController.textFields![1]).text = "Lake"
        (alertController.textFields![2]).text = "Mentor"
        (alertController.textFields![3]).text = "N8BC"
        (alertController.textFields![4]).text = "147.165"
        (alertController.textFields![5]).text = "147.765"
        (alertController.textFields![6]).text = "110.9"
        (alertController.textFields![7]).text = "110.9"
        (alertController.textFields![8]).text = "+"
        (alertController.textFields![9]).text = "OPEN"
    }


    // MARK: - Segues

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showDetail" {
            if let indexPath = tableView.indexPathForSelectedRow {
            let object = fetchedResultsController.object(at: indexPath)
                let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
                controller.detailItem = object
                controller.navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem
                controller.navigationItem.leftItemsSupplementBackButton = true
            }
        }
    }

    // MARK: - Table View

    override func numberOfSections(in tableView: UITableView) -> Int {
        return fetchedResultsController.sections?.count ?? 0
    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        //return "Section \(section)"
        //return "Ohio"
        if let sections = fetchedResultsController.sections {
            let currentSection = sections[section]
            return String(currentSection.name)
        }
        return nil
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let sectionInfo = fetchedResultsController.sections![section]
        return sectionInfo.numberOfObjects
    }

    // *** Save, allows you to revert to standard cell
//    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
//        let repeater = fetchedResultsController.object(at: indexPath)
//        //configureCell(cell, withEvent: event)
//        configureCell(cell, withEvent: repeater)
//        return cell
//    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellTableIdentifier, for: indexPath) as! CustomCell
        let repeater = fetchedResultsController.object(at: indexPath)
        cell.call = repeater.call!
        //cell.state = repeater.state!
        cell.city = repeater.location!
        return cell
    }

    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            let context = fetchedResultsController.managedObjectContext
            context.delete(fetchedResultsController.object(at: indexPath))

            do {
                try context.save()
            } catch {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() 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.
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        self.performSegue(withIdentifier: "showDetail", sender:tableView)
    }

    func configureCell(_ cell: UITableViewCell, withEvent repeater: Repeaters) {
                cell.textLabel!.text = repeater.call!.description
    }

    // MARK: - Fetched results controller

    var fetchedResultsController: NSFetchedResultsController<Repeaters> {
    if _fetchedResultsController != nil {
        return _fetchedResultsController!
    }
        let fetchRequest: NSFetchRequest<Repeaters> = Repeaters.fetchRequest()

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

        // Edit the sort key as appropriate.
        let sortDescriptor = NSSortDescriptor(key: "call", ascending: false)

        fetchRequest.sortDescriptors = [sortDescriptor]

        // 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: self.managedObjectContext!, sectionNameKeyPath: "state", cacheName: "Master")
        aFetchedResultsController.delegate = self
        _fetchedResultsController = aFetchedResultsController

        do {
            try _fetchedResultsController!.performFetch()
        } catch {
             // Replace this implementation with code to handle the error appropriately.
             // fatalError() 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. 
             let nserror = error as NSError
             fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }

        return _fetchedResultsController!
    }    
    var _fetchedResultsController: NSFetchedResultsController<Repeaters>? = nil

    func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.beginUpdates()
    }

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange sectionInfo: NSFetchedResultsSectionInfo, atSectionIndex sectionIndex: Int, for type: NSFetchedResultsChangeType) {
        switch type {
            case .insert:
                tableView.insertSections(IndexSet(integer: sectionIndex), with: .fade)
            case .delete:
                tableView.deleteSections(IndexSet(integer: sectionIndex), with: .fade)
            default:
                return
        }
    }

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
        switch type {
            case .insert:
                tableView.insertRows(at: [newIndexPath!], with: .fade)
            case .delete:
                tableView.deleteRows(at: [indexPath!], with: .fade)
            case .update:
                //configureCell(tableView.cellForRow(at: indexPath!)!, withEvent: anObject as! Repeaters)
                print()
            case .move:
                //configureCell(tableView.cellForRow(at: indexPath!)!, withEvent: anObject as! Repeaters)
                //tableView.moveRow(at: indexPath!, to: newIndexPath!)
                print()
        }
    }

    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.endUpdates()
    }

    /*
     // Implementing the above methods to update the table view in response to individual changes may have performance implications if a large number of changes are made simultaneously. If this proves to be an issue, you can instead just implement controllerDidChangeContent: which notifies the delegate that all section and object changes have been processed.

     func controllerDidChangeContent(controller: NSFetchedResultsController) {
         // In the simplest, most efficient, case, reload the table view.
         tableView.reloadData()
     }
     */
}
swift xcode tableview sections
1个回答
0
投票

您可以尝试通过加入适量的委托细胞重新加载表,例如

protocol DetailsCellDelegate: class {
    func updateTable(with: Data)
}

并通过调用delegate?.updateTable(with: data)与您的数据进行该委托

© www.soinside.com 2019 - 2024. All rights reserved.