FetchResultController не может получить данные - PullRequest
0 голосов
/ 27 декабря 2018

Я новичок в ios App Development.Я пытаюсь сделать простое приложение, которое содержит tableView, мы можем добавить строки в tableView, и оно может сохранить эти данные в базе данных, используя CoreData.Я использую NSFetchedResultController для достижения этой цели, но когда я пытаюсь запустить его в симуляторе, данные, которые я добавляю не в базу данных, не в состоянии получить.Я пробую разные решения от других, но не могу решить их.

CoreDataStack.swift

import Foundation
import CoreData

class CoreDataStack {
    private init() {}
    static let shared = CoreDataStack()
    lazy var context = CoreDataStack.shared.persistentContainer.viewContext
    var fetchedResultsController: NSFetchedResultsController<UserEntity> {
        let fetchRequest: NSFetchRequest<UserEntity> = UserEntity.fetchRequest()
        let nameSortDescriptor = NSSortDescriptor(key: "name", ascending: true)
        let passwordSortDescriptor = NSSortDescriptor(key: "password", ascending: true)
        fetchRequest.sortDescriptors = [nameSortDescriptor,passwordSortDescriptor]
        let fetchResultsController = NSFetchedResultsController<UserEntity>(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
        return fetchResultsController
    }
    lazy var persistentContainer: NSPersistentContainer = {

        let container = NSPersistentContainer(name: "NSFRCCoreData")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {

                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        return container
    }()

    // MARK: - Core Data Saving support

    func saveContext () {
        if context.hasChanges {
            do {
                try context.save()
            } catch {

                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
    }

}

и My ViewController

import UIKit
import CoreData
class ViewController: UIViewController {
 let fetchResultController = CoreDataStack.shared.fetchedResultsController
    @IBOutlet weak var tableView: UITableView!
    override func viewDidLoad() {
        super.viewDidLoad()
        print(NSTemporaryDirectory())
        title = "List"
        tableView.dataSource = self

    }
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        CoreDataStack.shared.fetchedResultsController.delegate = self
        try! CoreDataStack.shared.fetchedResultsController.performFetch()

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

    @IBAction func addItems(_ sender: UIBarButtonItem) {
        let alert =  UIAlertController(title: "Enter The Item Name", message: nil, preferredStyle: .alert)
        alert.addTextField(configurationHandler: nil)
        alert .addTextField { (passwordTextField) in
            let placeholder = NSAttributedString(string: "Password", attributes: nil)
            passwordTextField.attributedPlaceholder = placeholder
        }
        let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
        let save = UIAlertAction(title: "Save", style:.default) { [unowned self] (action) in
            guard let nameTextfield = alert.textFields?.first, let name = nameTextfield.text else {
                return
            }
            guard let passwordTextfield = alert.textFields?[1], let password = passwordTextfield.text else {
                return
            }
            let entity = NSEntityDescription.entity(forEntityName: "UserEntity", in: CoreDataStack.shared.context)
            let userEntity = UserEntity(entity: entity!, insertInto: CoreDataStack.shared.context)
            userEntity.name = name
            userEntity.password = password
            try? CoreDataStack.shared.context.save()

            self.tableView.reloadData()
        }
        alert.addAction(cancel)
        alert.addAction(save)
        self.present(alert, animated: true, completion: nil)
    }


}

extension ViewController: UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        guard let sectionCount = CoreDataStack.shared.fetchedResultsController.sections?.count else {
            return 0
        }
        return sectionCount
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        guard let sections = CoreDataStack.shared.fetchedResultsController.sections else {
            return 0
        }

        return sections[section].numberOfObjects
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "DataCell", for: indexPath)
         let userEntity = CoreDataStack.shared.fetchedResultsController.object(at: indexPath)
        cell.textLabel?.text = userEntity.name
        cell.detailTextLabel?.text = userEntity.password
        return cell

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

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
        switch(type){
        case .insert:
            if let indexPath = newIndexPath {
                tableView.insertRows(at: [indexPath], with: .fade)
            }

        case .delete:
            if let indexPath = indexPath {
                tableView.deleteRows(at: [indexPath], with: .fade)
            }
        case .move:
            if let indexPath = indexPath, let newIndexPath = newIndexPath {
                tableView.moveRow(at: indexPath, to: newIndexPath)
            }
        case .update:
            if let indexPath = indexPath, let cell = tableView.cellForRow(at: indexPath){
                cell.textLabel?.text = "Hello"
            }
        }
    }
    func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
        tableView.endUpdates()
    }
}

TableView не показывает никаких данных, но когда я проверяю с помощью браузера sqlite, он содержитданные сохранения.

1 Ответ

0 голосов
/ 28 декабря 2018

Ваш fetchedResultsController является вычисляемым свойством, которое будет возвращать новый экземпляр FRC при каждой его оценке.Следовательно, performFetch выполняется на экземпляре, отличном от FRC в методах источника данных tableView.

...