Sort descriptors with NSFetchedResultsController - Swift
P

1

6

I have a UITableView fed from Core Data with an NSFetchedResultsController returning the Location entities. The default sorting (and section headers) is via the first letter of the entity's name. This works (albeit I'm still trying to combine upper and lower case into the same section properly.) The user can choose to order the table by one of three optional categories (which are attributes of the entity) and then these categories are sorted by entity name.

When I set to sorting by category I get the following runtime error:

[_TtCSs23_ContiguousArrayStorage00007F80513B59D0 key]: unrecognized selector sent to instance 0x7f80513b5720

This is my NSFetchedResultsController:

var sectionNameKeyPathString1: String?
var sectionNameKeyPathString2: String?

var fetchedResultsController: NSFetchedResultsController {
    if _fetchedResultsController != nil {
        return _fetchedResultsController!
    }

    let fetchRequest = NSFetchRequest()
    // Edit the entity name as appropriate.
    let entity = NSEntityDescription.entityForName("Location", inManagedObjectContext: self.managedObjectContext!)
    fetchRequest.entity = entity

    // Set the batch size to a suitable number.
    fetchRequest.fetchBatchSize = 20

    // Edit the sort key as appropriate.
    if sectionNameKeyPathString1 != nil {
        let sortDescriptor1 = NSSortDescriptor(key: sectionNameKeyPathString1!, ascending: true)
        let sortDescriptor2 = NSSortDescriptor(key: sectionNameKeyPathString2!, ascending: true)
        let sortDescriptors = [sortDescriptor1, sortDescriptor2]
        fetchRequest.sortDescriptors = [sortDescriptors]
    } else {
        let sortDescriptor = NSSortDescriptor(key: "locationName", ascending: true)
        fetchRequest.sortDescriptors = [sortDescriptor]
    }

    var sectionNameKeyPath: String
    if sectionNameKeyPathString1 == nil {
        sectionNameKeyPath = "firstLetterAsCap"
    } else {
        sectionNameKeyPath = sectionNameKeyPathString1!
    }

    // Edit the section name key path and cache name if appropriate.
    // nil for section name key path means "no sections".
    let aFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath: sectionNameKeyPath, cacheName: "Locations")
    aFetchedResultsController.delegate = self
    _fetchedResultsController = aFetchedResultsController

    var error: NSError? = nil
    if !_fetchedResultsController!.performFetch(&error) {
        // TODO: Handle this error
        // Replace this implementation with code to handle the error appropriately.
        // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        //println("Unresolved error \(error), \(error.userInfo)")
        abort()
    }

    return _fetchedResultsController!
}

Using breakpoints I am confident that, for example, sectionNameKeyPathString1 = "category1" and sectionNameKeyPathString2 = "locationName" and also that sectionNameKeyPath = "category1" so the key path matches the first sort descriptor.

I had this working in Obj-C but now I'm pulling my hair out and sure I'm suffering from bug-blindness.

Placate answered 5/9, 2014 at 10:33 Comment(0)
E
11

Is it that you just have too many []?

    let sortDescriptors = [sortDescriptor1, sortDescriptor2] // <- an [NSSortDescriptor]
    fetchRequest.sortDescriptors = [sortDescriptors] // <- now an [[NSSortDescriptor]]

should just be:

    fetchRequest.sortDescriptors = [sortDescriptor1, sortDescriptor2]
Edge answered 5/9, 2014 at 10:39 Comment(2)
You answered my question while I was still editing it. Thank you! I'll accept your answer when the time limit is up. I'm so happy people are staring at me.Placate
That's so weird, the same happened to me! Must have double-tapped square bracket by accident and not noticed it due to my initialising the descriptors within the array initialiser and being too used to having to put methods like that in square brackets from ObjC.Sarpedon

© 2022 - 2024 — McMap. All rights reserved.