核心数据对象被保存,但在我弹出相关对象表然后出现之前不会出现在表中

Posted

技术标签:

【中文标题】核心数据对象被保存,但在我弹出相关对象表然后出现之前不会出现在表中【英文标题】:Core data object get saved, but doesn't show up in table until I pop to related object table and then come forward 【发布时间】:2016-11-28 20:01:56 【问题描述】:

我在导航控制器中嵌入了三个视图控制器。

第一个视图控制器是一个测试列表,它使用 fetchedResultsController 来填充表格。

第二个视图控制器是详细视图控制器,它允许添加新测试、编辑其详细信息、保存新测试或向测试添加问题。它还包括一个问题表,其中也填充了 fetchedResultsController。

我遇到的问题是,当我保存了现有的测试时,然后当我去添加问题时,当我弹出回到 TestDetailsVC 时,它们会正确填充表格,但是,如果我要添加新的测试,然后添加新问题,测试保存到核心数据,然后在 QuestionDetailsVC 问题也保存到核心数据。但是,当我回到 TestDetailsVC 时,新问题不会填充表格。但是,当我导航回 TestListVC 然后继续前进时,问题就会正确填充表格。我试图让问题在我第一次弹回表格时填充表格。当视图加载时表不应该重新获取这些数据,并且当我导航回来时表是否应该正常工作,因为这些对象保存在核心数据中?为什么它适用于以前保存的测试对象,但不适用于新保存的测试对象?

我在 TestDetailsVC 中保存新测试的代码是:

//if we tap on a row, then we select that question to edit
//if a question is selected, we will pass that information over to
//the question editor view so it can be edited    
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    //make sure there is at least one question
    //objs = means object selected
    if let objs = controller.fetchedObjects, objs.count > 0 
        //if there is, keep track of the test which is selected
        let question = objs[indexPath.row]
        //pass along that test to the editor to be edited
        //the sender is the selected test at that particular row
        performSegue(withIdentifier: "EditQuestionSegue", sender: question)
    



//we need to get ready to do the segue before we call it
override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    if let identifier = segue.identifier 
        switch identifier 
        case "EditQuestionSegue":
            //find the question needing to be edited
            //pass this along to the question editing view controller
            if let destination = segue.destination as? QuestionDetailsVC 
            if let question = sender as? Question 
                destination.questionToEdit = question
                //pass along the test that the question is
                //related to also
                if let test = testToEdit 
                    destination.testToEdit = test
                    
                
            
        case "AddNewQuestionSegue":
            //if no test to edit got passed in, it means
            //we're now editing a new test
            //once we type in the test title, then we have to
            //make sure the test has been saved if it's new test
            //before we go on to edit questions
            if testToEdit == nil 

                saveTestBeforeAddingQuestion()
                //make sure we set up as if new
                //before we start adding questions
                //these are called in the view did load
            
            if let destination = segue.destination as? QuestionDetailsVC 
                if let test = testToEdit 
                    destination.testToEdit = test
                
            
        default:
            print("no segue this time")
        
    


func saveTestBeforeAddingQuestion() 

    var test: Test!


    //if there's not a passed in value into the testToEdit core data
    //object test entity, then we're going to edit as if new
    if testToEdit == nil 
        //then instantiate a new test object ready to be written to
        test = Test(context: context)
     else 
        test = testToEdit
    

    if let title = titleTextField.text 
        test.title = title
    


    if let abrevTitle = abrevTitleTextField.text 
        test.abrevTitle = abrevTitle
    
    if let author = authorTextField 
        test.author = author.text
    
    if let publisher = publisherTextField 
        test.publisher = publisher.text
    


     ad.saveContext()
    //since we have now saved a new test
    //let's put that test into our testToEdit variable
    //so we can pass it along to the next view controller
    //during our segue
     if let newTestCreated = test 
        testToEdit = newTestCreated
    

我保存新问题的代码是:

   @IBAction func savePressed(_ sender: UIButton) 

          var question: Question!

        //if there's not a passed in value into the questionToEdit core data
        //object test entity, then we're going to edit as if new
        if questionToEdit == nil 
            //then instantiate a new test object ready to be written to
            question = Question(context: context)
         else 
            question = questionToEdit
        

        //make sure to relate the question added to the testToEdit test
        question.test = self.testToEdit

        //if there is something in the sentence text field
        //then assign that value to the question.sentence attribute
        //of the sentence entity in our core data context
        if let sentence = questionSentenceTextField.text 
            question.sentence = sentence
        
        if let identifier = questionIdentifierTextField.text 
            question.identifier = identifier
        
        if let displayOrder = questionDisplayOrderTextField.text 
            question.displayOrder = Int(displayOrder) as NSNumber?
        

        // save the context
        ad.saveContext()

        _ = navigationController?.popViewController(animated: true)

    

【问题讨论】:

【参考方案1】:

我花了几天时间试图加载问题表,但最后发现它没有重新加载,因为当我弹回视图控制器时,它不会使用 fetchedResultsController 自动重新加载表。所以我不得不调用 viewWillAppear 方法重新获取数据,然后重新加载 tableView:

(TestDetailsVC)

    override func viewWillAppear(_ animated: Bool) 
        guard testToEdit != nil else return
        attempFetch()
        tableView.reloadData()
    

【讨论】:

以上是关于核心数据对象被保存,但在我弹出相关对象表然后出现之前不会出现在表中的主要内容,如果未能解决你的问题,请参考以下文章

从核心数据中获取数据

Kettle实战之(2)过滤记录

核心数据:托管对象与上下文一起保存后如何撤消操作

停止与核心数据托管对象相关的堆增长

如何将获取的对象保存到核心数据

Bootstrap Modal ajax 保存多条记录,bootstrapValidator