Why NSFetchedResultsController is not being updated with new data?

前端 未结 4 754
我在风中等你
我在风中等你 2021-01-18 05:33

My Core Data model has two entities: Author and Book with a To-Many relationship (one author->many books). In the main view I display a list of

相关标签:
4条回答
  • 2021-01-18 05:56

    Today with Swift everything is easier.

    1. You implement NSFetchedResultsControllerDelegate in your controller
    2. Set your controller as delegate of your NSFetchedResultsController.
    3. Do not use performFetch on your fetchedResultsController, it swallows up the event which normally goes to the delegate.
    4. Change a Managed object -> delegate methods should be called.
    0 讨论(0)
  • 2021-01-18 05:57

    Why don't you commit the transactions saving changes?

    - (void)saveAuthorName:(NSString *)newName {
        for (Book* book in author.books) {
            [book willChangeValueForKey:@"author"];
        }
    
        author.name = newName;
    
        for (Book* book in author.books) {
            [book didChangeValueForKey:@"author"];
        }
        NSError * error ;
        if( ![self.moc save:&error] ) {
             ..... do something ..
        }
    }
    
    0 讨论(0)
  • 2021-01-18 05:59

    I know this is a very old question, but after spending so much time researching, testing and trying to resolve the same situation for myself, I want to share my findings. I am fairly certain that this is an Apple bug and I have filed Feedback FB7960282 for the issue of the name property of the NSFetchedResultsSectionInfo not always having the correct value.

    My Objc is a little rusty, so I will give my the workaround in Swift.

    // This is a workaround for an apparent bug where the name property of an NSFetchedResultsSectionInfo
    // element sometimes provides an incorrect name for the section.
    private func name(for section: NSFetchedResultsSectionInfo) -> String {
    
        // The objects property of the NSFetchedResultsSectionInfo should always have at least one element
        let object = section.objects?.first as! NSObject
        // The name of the section should be the value of the Key Path of all objects in the array
        let name = object.value(forKeyPath: self.frc.sectionNameKeyPath!) as? String ?? ""
        return name
    }
    

    The above function assumes that self.frc is your fetched results controller.

    BTW, since your query is returning books, if you want to react to changes to authors, you should observe for NSManagedObjectContextDidSave notifications.

    0 讨论(0)
  • 2021-01-18 06:00

    Generally you should not need to save the changes if you are dealing with a single NSManagedObjectContext for both the NSFetchedResultsController and the UIViewController that is making the changes.

    That does not apply if you have more than one NSManagedObjectContext.

    Assuming you have one NSManagedObjectContext, I would make sure you have the delegate set on the NSFetchedResultsController and put break points in the delegate methods to see if you are getting any callbacks at all.

    I would also use the debugger and print out the pointers for the NSManagedObject(s) you are working with and make sure they are the same. If they are not then it would point to an issue with the NSManagedObjectContext.

    Response #1

    Hmmm, still a little fuzzy. Are you saying the number of sections is incorrect?

    Based on your code posted you are simply retrieving the NSManagedObject instances from the NSFetchedResultsController. Perhaps there is some confusion as to what that is?

    The NSFetchedResultsController is merely a container that has one or more sections. Those sections are also just a container that holds one or more NSManagedObject instances. Those are the same instances of NSManagedObject that you would access anywhere else in your application (assuming a single NSManagedObjectContext design).

    Therefore if you change the data in a NSManagedObject anywhere in your application it will be updated in the NSFetchedResultsController because it is the same object, not a copy but the exact same object.

    So this leads to a couple of questions:

    1. How are you changing the author's name in this other view?
    2. Is the author name in the cell old or just the section header? 
    3. What do your delegate methods look like?
    4. Are you certain that your -[UITableViewDatasource tableView: titleForHeaderInSection:] is firing after you return from the edit?
    5. What NSFetchedResultsControllerDelegate methods are firing upon the return?

    Response #2

    Are you implementing -controller: didChangeSection: atIndex: forChangeType:? If not, please do so and tell me if it fires. If it does fire, when does it fire? Before or after the call to -[UITableViewDatasource tableView: titleForHeaderInSection:]?

    Response #3

    This is starting to sound like an Apple bug.

    A couple of thoughts:

    1. What happens if you do a -performFetch: after the author is tickled? I wonder if that would work.
    2. I strongly suggest that you create a test case for this. You can then submit it to Apple for a radar (vital) and I can play with the test also and see if there is a clean solution.
    0 讨论(0)
提交回复
热议问题