虽然项目正在核心数据中保存,但在重新启动之前无法查看它们

时间:2016-09-04 06:39:13

标签: ios swift multithreading core-data parent-child

以下是Warning: StandardWrapperValve[LoginServlet]: Servlet.service() for servlet LoginServlet threw exception java.lang.NoClassDefFoundError: Could not initialize class org.apache.xml.security.Init at org.opensaml.DefaultBootstrap.initializeXMLSecurity(DefaultBootstrap.java:195) at org.opensaml.DefaultBootstrap.bootstrap(DefaultBootstrap.java:98) at opensamltest1.SAMLHelper.printSAMLObject(SAMLHelper.java:180) at LoginServlet.processRequest(LoginServlet.java:53) at LoginServlet.doPost(LoginServlet.java:100) at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1682) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:318) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:160) at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:734) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:416) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:283) at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167) at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206) at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180) at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235) at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:283) at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:200) at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:132) at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:111) at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77) at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:536) at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56) at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:591) at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:571) at java.lang.Thread.run(Thread.java:745) 中使用FetchedResultsController的示例,而另一个ViewController的保存未传递给它。

  1. MainVC.swift

    ViewController
  2. AddRecordVC.swift

    lazy var coreDataManager = CoreDataManager()
    
    // Initialize fetched request
    private var fetchRecordRequestController: NSFetchedResultsController = NSFetchedResultsController()
    
    override func viewDidLoad() {
    super.viewDidLoad()
    
    // Do any additional setup after loading the view.
    
    // Initialize managedObjectContext
    let mainManagedObjectContext = coreDataManager.managedObjectContext
    
    // Create Fetch Request
    let fetchRequest = NSFetchRequest(entityName: "Record")
    
    // Configure Fetch Request
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false)]
    
    // Initialize Fetched Results Controller
    fetchRecordRequestController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: mainManagedObjectContext, sectionNameKeyPath: nil, cacheName: nil)
    
    // Configure Fetched Results Controller
    fetchRecordRequestController.delegate = self
    
    // Fetch data from object
    do {
        try fetchRecordRequestController.performFetch()
    } catch let fetchError as NSError {
        print("(RootViewController)fetchError: \(fetchError), \(fetchError.userInfo)")
    }
    
    // Add observer in NSNotificationCenter for NSManagedObjectContextObjectsDidChange
    NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(managedObjectContextObjectsDidChange), name: NSManagedObjectContextObjectsDidChangeNotification, object: mainManagedObjectContext)
    
    override func viewWillDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
    // MARK: - NSFetchedResultsController Delegate Methods
    
    func controllerWillChangeContent(controller: NSFetchedResultsController) {
        tableView.beginUpdates()
    }
    
    // Delete corresponding row in tableView
    func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
    switch type {
    case .Insert:
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
    case .Delete:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
    case .Update:
        tableView.reloadRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
    case .Move:
        tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
        tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
    }
    }
    
    func controllerDidChangeContent(controller: NSFetchedResultsController) {
    tableView.endUpdates()
    }
    
    func managedObjectContextObjectsDidChange(notification: NSNotification) {
    
    let mainManagedObjectContext = coreDataManager.managedObjectContext
    guard let userInfo = notification.userInfo else { return }
    
    if let inserts = userInfo[NSInsertedObjectsKey] as? Set<NSManagedObject> where inserts.count > 0 {
        print("--- INSERTS ---")
        print(inserts)
        print("+++++++++++++++")
        do {
            try mainManagedObjectContext.save()
        } catch let saveError as NSError {
            print("(RootViewController)saveError: \(saveError), \(saveError.userInfo)")
        }
    }
    
    if let updates = userInfo[NSUpdatedObjectsKey] as? Set<NSManagedObject> where updates.count > 0 {
        print("--- UPDATES ---")
        for update in updates {
            print(update.changedValues())
        }
        print("+++++++++++++++")
    }
    
    if let deletes = userInfo[NSDeletedObjectsKey] as? Set<NSManagedObject> where deletes.count > 0 {
        print("--- DELETES ---")
        print(deletes)
        print("+++++++++++++++")
    }
    }
    
  3. 一旦AddRuleVC回到RootVC,视图就不会刷新。 但是在应用程序退出并重新启动后,它确实显示了数据。 CoreDataStack使用了一个单独的类,如下所示。

    1. CoreDataManager.swift

      // Method to save the extracted values to CoreData Objects
      private func saveValues() {
      // Initializing
      let mainManagedObjectContext = coreDataManager.managedObjectContext
      // Initialize entity description
      let RecordDescription = NSEntityDescription.entityForName("Record",inManagedObjectContext:mainManagedObjectContext)
      let record = Record(entity: RecordDescription!, insertIntoManagedObjectContext: mainManagedObjectContext)
      // Set object values from temporary variables
      record.date = dateTemp!
      record.tareWeight = tareWeightTemp
      record.grossWeight = grossWeightTemp
      record.nettWeight = nettWeightTemp
      record.numberOfBags = numberOfBagsTemp
      record.weightOfBags = weightOfBagsTemp
      record.rivaju = rivajuTemp
      record.putti = puttiTemp
      record.rateOfPaddy = rateOfPaddyTemp
      record.amount = amountTemp
      // Save the object
      do {
          if mainManagedObjectContext.hasChanges {
              try mainManagedObjectContext.save()
          }
      } catch let saveError as NSError {
          print("(AddRecordViewController)saveError: \(saveError), \(saveError.userInfo)")
      }
      }
      

      // MARK: - 助手方法

      class CoreDataManager: NSObject {
      
      // MARK: - Core Data Stack
      
      lazy var managedObjectModel: NSManagedObjectModel = {
      let modelURL = NSBundle.mainBundle().URLForResource("App Name", withExtension: "momd")!
      return NSManagedObjectModel(contentsOfURL: modelURL)!
      }()
      
      lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
      // Create the coordinator and store
      let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
      let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
      var failureReason = "There was an error creating or loading the application's saved data."
      do {
          try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
      } catch {
          // Report any error we got.
          var dict = [String: AnyObject]()
          dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
          dict[NSLocalizedFailureReasonErrorKey] = failureReason
      
          dict[NSUnderlyingErrorKey] = error as NSError
          let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
          NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
          abort()
      }
      
      return coordinator
      }()
      
      lazy var managedObjectContext: NSManagedObjectContext = {
      let coordinator = self.persistentStoreCoordinator
      var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
      managedObjectContext.persistentStoreCoordinator = coordinator
      managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
      return managedObjectContext
      }()
      

2 个答案:

答案 0 :(得分:2)

您的CoreDataManager类在AddRecordVC内生成一个新的托管对象上下文,与MainVC中的托管对象上下文不同,因此当您保存第二个上下文时,将更新持久性存储,但更改将赢得&除非您合并更改,否则将反映在第一个上下文中。

这不好,你只需要一个主线程的上下文。所以你应该做的是使用依赖注入来管理对象上下文。在您的应用启动时启动CoreDataManager,然后将上下文注入MainVC,然后当您转到AddRecordVC时,也只是传递相同的上下文。

答案 1 :(得分:0)

保存新项目后,您需要通过异步执行tableview.reloadData()重新加载表格视图。