iamsim.me
iamsim.me

Reputation: 580

Sort fetch request based on relationship attribute

Let's say I have two entities; Item and LocalizableString. The LocalizableString entity has two attributes; string and locale. The Item entity has a to-many relationship to LocalizableString called localizedTitles. Where there's one string entity per "locale".

Now, in my app, I have some context/setting that determines what locale I want to use when showing the UI. So let's say I have a UITableViewController with an NSFetchedResultsController handling the data flow.

My question is: can I sort the Item entities based on the LocalizableString's string property where locale is for example en? And can I do this in the fetch request, not after having fetched all items?

Upvotes: 0

Views: 557

Answers (2)

iamsim.me
iamsim.me

Reputation: 580

I ended up doing a fetch request for my LocalizableString entity instead. With a predicate that checks the locale and the inverse relationship:

NSPredicate(format: "locale == %@ AND itemName != nil", locale)

Upvotes: 0

Mundi
Mundi

Reputation: 80265

Sure you can do that, but you do not have to fetch any particular locale upfront. Your fetched results controller would just fetch the Item objects, and you can then refer to the correct string as you need it.

One way to implement this is to add a convenience function to the Item class, something like the following

func titleWithLocale(identifier: String) -> String? {
   if let title = self.localizedTitles.filter 
         { $0.locale == identifier }
         .first as? LocalizableString {
     return title.string
   }
   return nil
}

Most likely you will have to tweak this code to conform to the strict typing of Swift, but you get the idea.

If you need to sort by the title string, perhaps you need a different approach. If you know that each Item has a localized title in the respective locale you can fetch the LocalizedTitle entity with a predicate the filters for the locale:

 request.predicate = NSPredicate(format: "locale = %@", "en")

Obviously, you can sort by string with the usual sort descriptors. Now, to populate your table, you get to the item by following the relationshp in the other direction.

 let title = fetchedResultsController.objectAtIndexPath(indexPath)!
 let item = title.item

Upvotes: 1

Related Questions