简体   繁体   中英

Displaying tableView items by CoreData attribute

I am trying to group section 0 my tableView by the "category" attribute of an item.

Example:

Drinks: (item.category = header)
Dr. Prepper
Coke
Pepsi
Kitchen: (item.category = header)
Pots
Pans...etc.
CrossOff(header)
items

I still want section1 to be the item.slcross (or the last section if each group has to be their own section...and it doesn't have to be grouped).

When I change the secondarySortDescriptor key from "slitem" to "slcategory" and use the sectionHeader code below, it returns "nil". I also tried using

let sectionHeader2 = "\\(item.valueForKeyPath("slcategory"))" but still had the same effect with both "slitem" and "slcategory".

Do I have to use a sort descriptor for each category or is there a way to make it pull the category attribute for the item and group the like categories together?

FRC set up:

let moc = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext

var frc : NSFetchedResultsController = NSFetchedResultsController()

var selectedItem : List?

func itemFetchRequest() -> NSFetchRequest{

    let fetchRequest = NSFetchRequest(entityName: "List")
    let primarySortDescription = NSSortDescriptor(key: "slcross", ascending: true)
    let secondarySortDescription = NSSortDescriptor(key: "slitem", ascending: true)
    fetchRequest.sortDescriptors = [primarySortDescription, secondarySortDescription]
    fetchRequest.predicate = NSPredicate(format:"slist == true")
    return fetchRequest
}

func getFetchRequetController() ->NSFetchedResultsController{

    frc = NSFetchedResultsController(fetchRequest: itemFetchRequest(), managedObjectContext: moc, sectionNameKeyPath: "slcross", cacheName: nil)
    return frc
}

TableViewHeaders:

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String?{

    let entityDescription = NSEntityDescription.entityForName("List", inManagedObjectContext: moc)

    let item = List(entity: entityDescription!, insertIntoManagedObjectContext: moc)

    let sectionHeader = "\(item.slcategory)"
    let sectionHeader1 = "Items in Cart - #\(frc.sections![section].numberOfObjects)"
    if (frc.sections!.count > 0) {
        let sectionInfo = frc.sections![section]
        if (sectionInfo.name == "0") { 
            return sectionHeader2
        } else {
            return sectionHeader1
        }
    } else {
        return nil
    }
}

There are a few ways to do this, but probably the easiest is to add a new method to your NSManagedObject subclass. The method returns a string which will be used as the title for the section; so if slcross is false, it returns the value of slcategory , and if slcross is true it returns "True":

func sectionIdentifier() -> String {
    if (self.slcross) {
        return "True"
    } else {
        return "\(self.slcategory)"
    }
}

(Note this code goes in your List class definition, not your view controller).

In the view controller, use this sectionIdentifier as the sectionNameKeyPath for your FRC:

frc = NSFetchedResultsController(fetchRequest: itemFetchRequest(), managedObjectContext: moc, sectionNameKeyPath: "sectionIdentifier", cacheName: nil)

For that to work, it is imperative that the objects are sorted correctly: first by slcross , then by slcategory :

let primarySortDescription = NSSortDescriptor(key: "slcross", ascending: true)
let secondarySortDescription = NSSortDescriptor(key: "slcategory", ascending: true)

Finally, amend your titleForHeaderInSection to use the section name (which the FRC gets from sectionIdentifier ), but replacing the "True" with your computed string:

func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String?{    
    if (frc.sections!.count > 0) {
        let sectionInfo = frc.sections![section]
        if (sectionInfo.name == "True") { 
            return "Items in Cart - #\(sectionInfo.numberOfObjects)"
        } else {
            return sectionInfo.name
        }
    } else {
        return nil
    }
}

From Apple Docs...

When you initialize the fetch results controller, you provide four parameters: ..... ....Optionally, a key path on result objects that returns the section name. The controller uses the key path to split the results into sections (passing nil indicates that the controller should generate a single section)..... After creating an instance, you invoke performFetch: to actually execute the fetch.

If you want to sort the sections by category then you need to make the sectionNameKeyPath argument in the NSFetchedResultsController init to be your "category" property instead of your "slcross" property.

When I've used this in the past I've also included that same property that I've set as the sectionNameKeyPath in my sort descriptors, but not sure if that is actually needed or not.

Hope I have answered your question?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM