2

I'm using a NSFetchedResultsController for my table view and I would like to have an index A-Z.

The problem is that if I use the entity's attribute for which I want to have section, it will return as many section as there are different names for this attribute.

So I was thinking to add another attribute in my NSManagedObject subclass. This attribute would be only the first letter of the other one.

So I found out this topic where they explain how to do it but:

  • it's an pretty old one so I was wondering if there were not any better option now
  • it's in Objective-C and I have to confess that I don't really master this language.

Although I tried to do what they said to do but it didn't work.

class Currency: NSManagedObject {

    @NSManaged var country: String
    @NSManaged var code: String
    
    func firstLetterCodeForSection() -> String {
        self.willAccessValueForKey("firstLetterCodeForSection")
        var tempString = self.valueForKey("code")!.uppercaseString
        tempString.removeRange(Range(start: tempString.startIndex, end:advance(tempString.startIndex, 1)))
        self.didAccessValueForKey("firstLetterCodeForSection")
        return tempString
    }
    
    func firstLetterCountryForSection() -> String {
        self.willAccessValueForKey("firstLetterCountryForSection")
        var tempString = self.valueForKey("country")!.uppercaseString
        tempString.removeRange(Range(start: tempString.startIndex, end:advance(tempString.startIndex, 1)))
        self.didAccessValueForKey("firstLetterCountryForSection")
        return tempString
    }
}

I set firstLetterCountryForSection and firstLetterCodeForSection as transient in the entity

And here is my NSFetchedResultsController:

fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: managedContext, sectionNameKeyPath: "firstLetterCountryForSection", cacheName: nil)

The sort is based whether on code or on country.

And... it doesn't work...

Am I missing something or doing something wrong?

Thanks for your help!

UPDATE:

I found the problem, it came from the line where I was substringing the first letter, I was actually keeping all the letters except the first one...

I replaced

tempString.removeRange(Range(start: tempString.startIndex, end:advance(tempString.startIndex, 1)))

by

tempString.removeRange(Range(start: advance(tempString.startIndex, 1), end:tempString.endIndex))

But now I have another questions. I tried it with:

func firstLetterCountryForSection() -> String { }

var firstLetterCountryForSection: String { }

dynamic var firstLetterCountryForSection: String? { }

and the result is the same, it's working (at least it looks like it). What's the difference? What's the best one to use?

Thanks again

Community
  • 1
  • 1
Nico
  • 6,269
  • 9
  • 45
  • 85
  • Could you give more information as to what's not working? Is it crashing? Are no sections being displayed? Furthermore, please post your code where you define the `NSFetchRequest` instance. – Alex Feb 20 '15 at 14:35
  • @Alexander it was a **fatal error: unexpectedly found nil while unwrapping an Optional value** when I reached the **func numberOfSectionsInTableView(tableView: UITableView) -> Int { }** method due actually to my problem (see my update) – Nico Feb 20 '15 at 21:28

2 Answers2

3

You're trying to use a function to calculate the section when you should be using a dynamic variable:

dynamic var section: String? {
    let characters = Array(code.uppercaseString)
    return characters[0]
}

and then your fetchedResultsController should look like this:

fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest(), managedObjectContext: managedObjectContext!, sectionNameKeyPath: "section", cacheName: "Root")

See my answer here for more info on setting up transient properties.

Community
  • 1
  • 1
Ian
  • 12,538
  • 5
  • 43
  • 62
0

In your case you are missing the @obj annotation on the transient property. Also, try adding the property to your model and make sure is marked as transient.

SergioM
  • 1,595
  • 1
  • 15
  • 27