Skip to content Skip to sidebar Skip to footer

Nsfetchedresultscontroller Not Sorting On Encrypted Attributes

I am trying to encrypt the attributes in my Core Data model using the transformable type but am experiencing a lot of issues trying to fetch back results once data has been persist

Solution 1:

There is some relevant information in the "Core Data Programming Guide".

You cannot fetch using a predicate based on transient properties (although you can use transient properties to filter in memory yourself). ... To summarize, though, if you execute a fetch directly, you should typically not add Objective-C-based predicates or sort descriptors to the fetch request. Instead you should apply these to the results of the fetch.

There are some interactions between fetching and the type of store. ... The SQL store, on the other hand, compiles the predicate and sort descriptors to SQL and evaluates the result in the database itself. This is done primarily for performance, but it means that evaluation happens in a non-Cocoa environment, and so sort descriptors (or predicates) that rely on Cocoa cannot work.

Since the transformer is applied to the data after fetching it from the SQLite store, using a transformed attribute as sort key will not produce the desired result.

Your Core Data error is probably caused by the fact that the sections are sorted using the encrypted data, but the sectionNameKeyPath of the FRC (which can be a transient attribute) gives the unencrypted data, which of course is inconsistent.

The only solution I can imagine is to store an additional unencrypted attribute that has enough information to be used as sort key (e.g. the person's initial letter).

Solution 2:

To the best of my knowledge, NSFetchRequest (when you use sqlite via CoreData) generates sql, use it on sqlite and returns result. So, while sqlite know nothing about your decrypting made by CoreData, it is impossible to sort result with NSFetchRequest using decrypted data.

Possible solution is to copy the result of NSFetchRequest into NSArray and do the sort over your encrypted fields manually. Another solution is to sort your data on every insert or modification and write the order to specific integer field and then while fetching sort over this field (it will save your performance if you do inserts and modification less frequent than fetching).

Solution 3:

The error you describe happens because sorting happens on the encrypted data in the database, but the NSFetchedResultsController later works on unencrypted data, and complains because the data is not sorted correctly for the section name.

To sort inside the db you would have to provide enough unencrypted info to sort, and to keep that info up-to-date.

For example, for sorting by first name, you could store an unencrypted attribute firstNameSection which contains the first letter of the firstName, and an attribute firstNameSortInfo which contains the position of that name for each index (for example "Aaron"=0, "Abby"=1, etc.

Then you could use firstNameSection and firstNameSortInfo for sorting, and firstNameSection as sectionNameKeyPath. This approach has (at least) two drawbacks:

  1. You would have to keep the firstNameSortInfo up-to-date, and this would need more writes than you may like, and the firstNameSortInfo sorting would have to be done in-memory (as it is done on unencrypted data).
  2. Some info about the encrypted data may be known to a potential attacker, which may weaken the encryption.

Post a Comment for "Nsfetchedresultscontroller Not Sorting On Encrypted Attributes"