在TableViewCells中查看Core Data的隐形问题

时间:2017-07-12 14:57:57

标签: ios iphone xcode core-data swift3

来自示例:https://drive.google.com/open?id=0B3d4jY23eLOoejdRWkE0SG1VMkk

步骤1.我实施了核心数据“数据库”。我现在有17条记录,想要通过TableView中的单元格查看所有这些记录... enter image description here

我做的就像在教程中一样,但它不起作用。我浪费了一个星期,并且找不到错误:(它加载完美,但数据不显示在单元格中:(所以...

import Foundation
import CoreData

@available(iOS 10.0, *)
class DatabaseController
{
    private init() { }
    
class func getContext() -> NSManagedObjectContext
{
    return persistentContainer.viewContext
}
    
// MARK: - Core Data stack
static var persistentContainer: NSPersistentContainer =
{
    let container = NSPersistentContainer.init(name: "Database")
    //let container = NSPersistentContainer(name: "Database")
    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
class func saveContext ()
{
        let context = persistentContainer.viewContext
        if context.hasChanges
        {
            do {
                try context.save()
            }
            catch {
                let nserror = error as NSError
                fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
            }
        }
}
    
}

主要是3个文件...“DatabaseController.swift”中的save / get / persistant容器 接下来“AppDelegate.Swift”......

func applicationWillTerminate(_ application: UIApplication)
{
    DatabaseController.saveContext()
}

// MARK: - Core Data stack
lazy var applicationDocumentsDirectory: NSURL =
{
    let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    return urls[urls.count-1] as NSURL
}()

lazy var managedObjectModel: NSManagedObjectModel =
{
    let modelURL = Bundle.main.url(forResource: "Database", withExtension: "momd")!
    return NSManagedObjectModel(contentsOf: modelURL)!
}()

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? =
{
    var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    let url = self.applicationDocumentsDirectory.appendingPathComponent("Database.sqlite")
    var error: NSError? = nil
    var failureReason = "There was an error creating or loading the application's saved data."

    do
    {
        try coordinator!.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)
    }
    catch {
        coordinator = nil

        let dict = NSMutableDictionary()
        dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
        dict[NSLocalizedFailureReasonErrorKey] = failureReason
        dict[NSUnderlyingErrorKey] = error
        let error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict as? [AnyHashable : Any])
        NSLog("Unresolved error \(String(describing: error)), \(error.userInfo)")
        print(error.localizedDescription)
        abort()
    }
    return coordinator
}()

lazy var managedObjectContext: NSManagedObjectContext? =
{
    let coordinator = self.persistentStoreCoordinator
    if coordinator == nil
    {
        return nil
    }

    var managedObjectContext = NSManagedObjectContext()
    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext
}()

负责DataCore的主要功能 和TableView的最终文件。在我将其作为DataCore之前,单元格显示为

if indexPath.row == 0 {
            cell.postImageView.image = UIImage(named: "ENTP")
            cell.postTitleLabel.text = "ENTP"
            cell.authorLabel.text = "Oleksandr Zheliezniak"
            cell.authorImageView.image = UIImage(named: "author"):
        } else if indexPath.row == 1 {
            cell.postImageView.image = UIImage(named: "INTJ")
            cell.postTitleLabel.text = "INTJ"
            cell.authorLabel.text = "Gabriel Theodoropoulos"
            cell.authorImageView.image = UIImage(named: "appcoda-300")
        } else if indexPath.row == 2 {
            cell.postImageView.image = UIImage(named: "ENTP")
            cell.postTitleLabel.text = "ENTJ"
            cell.authorLabel.text = "Gabriel Theodoropoulos"
            cell.authorImageView.image = UIImage(named: "appcoda-300")
        } else {
            cell.postImageView.image = UIImage(named: "СеКс")
            cell.postTitleLabel.text = "и виски"
            cell.authorLabel.text = "Кокс Карибский))"
            cell.authorImageView.image = UIImage(named: "appcoda-300")
        }

最终文件如下:

//
//  PersonTableViewController.swift
//
//  Created by Oleksandr Z 2017(c).
//
import UIKit
import Foundation
import CoreData

@available(iOS 10.0, *)
class PersonTableViewController: UITableViewController, NSFetchedResultsControllerDelegate
{
    @IBAction func addButtonPressed(_ sender: Any)
    {
        switchScreen()
    }
    @IBOutlet weak var menuButton:UIBarButtonItem!
    let moc: NSManagedObjectContext? = (UIApplication.shared.delegate as? AppDelegate)?.managedObjectContext
    var fetchedResultsController: NSFetchedResultsController<NSFetchRequestResult>?
    var valueToPass:String!
    //override var prefersStatusBarHidden: Bool {return true}

    override func viewDidLoad()
    {
        super.viewDidLoad()

        // MARK: - CORE DATA fetching out to the TableView
        fetchedResultsController?.delegate = self
        fetchedResultsController = NSFetchedResultsController(fetchRequest: IdentitiesFetchRequest(), managedObjectContext: self.moc!, sectionNameKeyPath: nil, cacheName: nil)
        do
        {
            try fetchedResultsController?.performFetch()
        }
        catch let error as NSError
        {
            fatalError("Failed to initialize FetchedResultsController: \(error)")
        }

        //Visualization
        if self.revealViewController() != nil
        {
            self.revealViewController().rearViewRevealWidth = 250
            self.revealViewController().frontViewShadowRadius = 10
            self.revealViewController().frontViewShadowColor = UIColor.black
            self.revealViewController().frontViewShadowOpacity = 1

            menuButton.target = self.revealViewController()
            menuButton.action = #selector(SWRevealViewController.revealToggle(_:))
            self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
        }
        self.clearsSelectionOnViewWillAppear = true
    }

    func IdentitiesFetchRequest() -> NSFetchRequest<NSFetchRequestResult>
    {
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Identity")
        let sortDescriptor = NSSortDescriptor(key: "lastModified", ascending: true)

        fetchRequest.predicate = nil
        fetchRequest.sortDescriptors = [sortDescriptor]
        fetchRequest.fetchBatchSize = 20
        fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc!, sectionNameKeyPath: nil, cacheName: nil)
        fetchedResultsController?.delegate = self
        do
        {
            try fetchedResultsController?.performFetch()
        }
        catch
        {
            fatalError("Failed to initialize FetchedResultsController: \(error)")
        }

        return fetchRequest
    }

    //MARK: NSFetchedResultsController Delegate Functions
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {    }

        switch editingStyle
        {
        case .delete:
            do
            {
                moc?.delete(fetchedResultsController?.object(at: indexPath) as! Identity)
                try moc?.save()
            }
            catch
            {
                print(error)
            }
        case .insert:
            break
        case .none:
            break
        }

    }

    func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?)
    {
        switch type
        {
        case NSFetchedResultsChangeType.insert:
            tableView.insertRows(at: NSArray(object: newIndexPath!) as! [IndexPath], with: UITableViewRowAnimation.fade)
            break
        case NSFetchedResultsChangeType.delete:
            tableView.deleteRows(at: NSArray(object: indexPath!) as! [IndexPath], with: UITableViewRowAnimation.fade)
            break
        case NSFetchedResultsChangeType.move:
            tableView.deleteRows(at: NSArray(object: indexPath!) as! [IndexPath], with: UITableViewRowAnimation.fade)
            tableView.insertRows(at: NSArray(object: newIndexPath!) as! [IndexPath], with: UITableViewRowAnimation.fade)
            break
        case NSFetchedResultsChangeType.update:
            tableView.cellForRow(at: indexPath! as IndexPath)
            break
            //default:
            //    break
        }
    }

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

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

    // MARK: - Table view data source
    override func numberOfSections(in tableView: UITableView) -> Int {
        // Return the number of sections.
        return fetchedResultsController?.sections?.count ?? 0
    }

    //Detailed viewCell
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    {
        print("You selected cell #\(indexPath.row)!")
        /*
         // Get Cell Label
         let indexPath = tableView.indexPathForSelectedRow!
         let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell

         valueToPass = currentCell.textLabel?.text
         performSegue(withIdentifier: "yourSegueIdentifer", sender: self)
         */
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?)
    {
        if (segue.identifier == "ShowPerson")
        {
            //var viewController = segue.destination as! PersonDetailViewController
            //viewController.passedValue = valueToPass
        }
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // Return the number of rows in the section.
        return fetchedResultsController?.sections?[section].numberOfObjects ?? 0
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as!PersonTableViewCell

        if let cellContact = fetchedResultsController?.object(at: indexPath) as? Identity
        {
            cell.textLabel?.text = "\(String(describing: cellContact.pName)), \(String(describing: cellContact.lastModified))"
        }

        let identityClassName:String = String(describing: Identity.self)
        //let typeClassName:String     = String(describing: Type.self)
        let identity:Identity = NSEntityDescription.insertNewObject(forEntityName: identityClassName, into: DatabaseController.getContext()) as! Identity
        //let type:Type = NSEntityDescription.insertNewObject(forEntityName: typeClassName, into: DatabaseController.getContext()) as! Type

        let fetchRequest:NSFetchRequest<Identity> = Identity.fetchRequest()
        do
        {
            let searchResults = try DatabaseController.getContext().fetch(fetchRequest)
            print("number of results: \(searchResults.count)")
            for result in searchResults as [Identity]
            {
                print("\(result.pName!) is \(result.accuracy)% Robesper. Updeted \(result.lastModified!).")

                cell.postImageView.image = UIImage(named: "ENTP")
                cell.postTitleLabel.text = identity.pName
                cell.authorLabel.text = identity.imType
                cell.authorImageView.image = UIImage(named: "author")
            }
        }
        catch   { print("Error: \(error)") }

        return cell
    }

    // Override to support rearranging the table view.
    override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to toIndexPath: IndexPath) {
    }

    // Override to support conditional rearranging of the table view.
    override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        // Return NO if you do not want the item to be re-orderable.
        return true
    }

    func switchScreen()
    {
        let mainStoryboard = UIStoryboard(name: "Main", bundle: Bundle.main)
        let vc : UIViewController = mainStoryboard.instantiateViewController(withIdentifier: "PersonDetail") as UIViewController
        self.present(vc, animated: false, completion: nil)
    }
}

尝试过的解决方案:Can't show the core data in tableview Swift但它没有帮助。尝试了所有类似的主题,但无法解决问题。

2 个答案:

答案 0 :(得分:0)

您似乎有两个单独的CoreData堆栈:一个由viewContext类设置,它使用NSPersistentContainer中的fetchedResultsController = NSFetchedResultsController(fetchRequest: IdentitiesFetchRequest(), managedObjectContext: self.moc!, sectionNameKeyPath: nil, cacheName: nil) (在iOS10中引入),另一个设置在AppDelegate,它使用旧版项目模板中的标准样板文件。你的FRC使用后者,而你的其余代码使用前者。

虽然这些似乎使用相同的模型文件,但我怀疑他们正在使用不同的持久存储。我想如果你改变这一行:

fetchedResultsController = NSFetchedResultsController(fetchRequest: IdentitiesFetchRequest(), managedObjectContext: DatabaseController.getContext(), sectionNameKeyPath: nil, cacheName: nil)

为:

{{1}}

您的FRC将使用与创建对象的代码相同的上下文,因此您应该看到一些结果。您的代码还有其他问题,正如Tom Harrington在评论中所说,您应该学习如何使用调试器来解决这些问题。

答案 1 :(得分:0)

1) AES_ENCRYPT()

3) DES_ENCRYPT()

4) ENCRYPT()

5) COMPRESS()

我尝试了很多。无论使用哪种解决方案(扩展,懒惰,直接)。

你应该确定两个变量:一个用于所有数据数组;第二个是数组中的单个数据。

这就是它的基本工作方式:

var identities : [Identity] = []

override func viewDidLoad()
{
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self