appropriate functions to override when executing subquery on encrypted binary data - ios

I'm considering encrypting every attribute in a sqlite data model. Encrypting the data clearly complicates accessing attribute values, saving attribute values, and searching for attribute values from the perspective of the view (in MVC).
I was thinking it may suffice to override NSFetchedResultsController methods fetchedResults and performFetch:, and NSManagedObjectContext method save:
I have also gotten into loads of trouble by assuming it was okay to override in the past.
Since this will likely take some time to work through all the details, I would like to know if anyone has discovered (and verified) an appropriate way to add codec mechanisms such that it's not necessary to encode and decode at every place in code where I search, access and save persistent data? And if so, what was the approach?

Related

How to implement a Persistent Cache in Siesta with a structured model layer

I'm using (and loving) Siesta to communicate with a REST web service in my Swift App. I have implemented a series of ResponseTransformers to map the API call responses to model classes so that the Siesta Resources are automatically parsed into object instances. This all works great.
I now want to implement a Siesta PersistantCache object to support an offline mode by having Siesta cache these objects to disk (rather than in memory) by storing them in Realm. I am not sure how to do this because the documentation says (about the EntityCache.writeEntity function):
This method can — and should — examine the entity’s content and/or headers and ignore it if it is not encodable. While they can apply type-based rules, however, cache implementations should not apply resource-based or url-based rules; use Resource.configure(...) to select which resources are cached and by whom.
In an attempt to conform to this guideline, I have created a specific PersistentCache object for each Resource type based on URL Pattern matching during Service Configuration:
class _GFSFAPI: Service {
private init() {
configure("/Challenge/*") { $0.config.persistentCache = SiestaRealmChallengeCache() }
}
However, since the EntityCache protocol methods only include a reference to the Entity (which exposes raw content but not the typed objects), I don't see how I can call the realm write methods during the call to EntityCache.writeEntity or how to pull the objects out of Realm during EntityCache.readEntity.
Any suggestions about how to approach this would be greatly appreciated.
Excellent question. Having a separate EntityCache implementations for each model could certainly work, though it seems like it might be burdensome to create all those little glue classes.
Models in the Cache
Your writeEntity() is called with whatever comes out at the end of all your response transformers. If your transformers are configured to spit out model classes, then writeEntity() sees models. If those models are Realm-friendly models, well, I don’t see any reason why you shouldn’t be able to just call realm.add(entity.content). (If that’s giving you problems, let me know with an update to the question.)
Conversely, when reading from the cache, what readEntity() returns does not go through the transformer pipeline again, so it should return exactly the same thing your transformers would have produced, i.e. models.
Cache Lookup Keys
The particular paragraph you quote from the docs is ill-written and perhaps a bit misleading. When it says you “should not apply resource-based or url-based rules,” it’s really just trying to dissuade you from parsing the forKey: parameter — which is secretly just a URL, but should remain opaque to cache implementations. However, any information you can gather from the given entity is fair game, including the type of entity.content.
The one wrinkle under the current API — and it is a serious wrinkle — is that you need to keep a mapping from Siesta’s key (which you should treat as opaque) to Realm objects of different types. You might do this by:
keeping a Realm model dedicated to keeping a polymorphic mapping from Siesta cache keys to Realm objects of various types,
by adding a siestaKey attribute and doing some kind of union query across models, or
by keeping a (cache key) → (model type, model ID) mapping outside of Realm.
I’d probably pursue the options in that order, but I believe you are in relatively unexplored (though perfectly reasonable) territory here using Realm as the backing for EntityCache. Once you’ve sussed out the options, I’d encourage you to file a Github issue for any suggested API improvements.

Core Data--pass name of entity or reference to entire entity?

I'm making a simple bank account tracker, for self-instructional purposes. I'm using Core Data to store three entities, related as in the screenshot:
WMMGTransaction objects are simply stored as they are recorded, and extracted as needed to feed tableviews and detail views. This will be done via NSFetchedResultsController and a predicate. I'm using MagicalRecord to access Core Data, if that matters.
My question is this:
When I pass WMMGAccount data from one VC to another, such as when creating a new account, or when selecting one from a list (via delegation as a rule), does it matter if I pass a reference to the entire entity, or can I just use an NSString bearing the .name of the account and identify the account when required with a predicate and an NSFetchedResultsController? I guess this is a strategy question, and may generate discussion, rather than having a cut and dried answer, but I'm wrestling with it, so I thought I'd ask.
It sounds like you're asking if you should pass an object to the code that needs it, or if you should pass information that could be used to look up the same object again.
Unless you need to use the managed object on a different thread or queue, you should always pass the actual object. No sense re-fetching an object you already have. It's extra work and code complexity that (unless there are some unusual extenuating details you didn't mention) won't help in any way.
If you are needing to use the object on a different queue or thread, passing information that can be used to look it up is the correct approach. But in that case-- don't pass the value of one of the properties. Use the managed object ID.
Core Data won't force name values to be unique, while the object's managedObjectID is unique. It's also faster when retrieving the object, because you can use objectForID: or existingObjectForID: instead of performing a fetch.

Storing large objects for a user session in Rails

I'm making use of Google API client gem which returns data and is then wrapped in the an object. I want to use this data between sessions. How should I store it? I thought at first I could serialize it then put it into a table, but ran into problems with the type of object it is an gave up. Actually thereafter I thought it would be neater to take the data I need and put it into an array of hashes (eg. for youtube videos - title, id, thumbnail etc) so I extracted what I needed and done so. Now, I have an array - should I store it in the database for the user or should I put it into a session var? Session var seems easier, no need to create an additional table etc but does that mean it will be stored as a cookie? Might be a rather large cookie then. Anyway advise here would be much appreciated.
First, with database storage: with ActiveRecord you can simply store JSON. So, if your object can be serialized correctly, than there are no problems to store it in DB. just add this line to your model:
serialize :data, JSON.
Though, I think you can perfectly use session var for that purpose. By default, yes, it will be stored as a cookie - but if you think it's too much information, you can configure rails to use server-side storage instead.

What's the simplest way to encode a chosen 'root' Core Data entity together with all of its relationships?

I use Core Data within my iOS 7 app to handle the editing and creation of entities. The entities have relationships between them, which all have inverses (as Apple advises).
For the sake of this question, let's pick any one of these interrelated entities and call it the Root entity: the thing that I want to encode with; the thing that logically lives on the 'top' of the hierarchy. I will call this the 'object graph'.
The question is:
What's the easiest way of encoding and decoding such an object graph to and from NSData?
The reason I want to do this is that I'd like my Core Data object graph to be persisted onto a cloud service, without the need of writing my own NSIncrementalStore subclass (it's a bit involved...!).
AutoCoding together with HRCoder almost looks like it could do the job, but I've experimented with this combination and it doesn't quite work with NSManagedObjects at the time of writing.
Still, I'm seeking alternatives. There can't only be one way to do this, surely.
It doesn't have to be JSON, but it'd be nice. Binary would be fine.
It seems to me you do not need to subclass NSIncrementalStore. You can create records and save them to your store with a plain vanilla store created via addPersistentStoreWithType:... with a NSPersistentStoreCoordinator.
The straight-forward way is to handle the incoming JSON by simply taking the data and copying it to the properties of your NSManagedObject subclasses, like this:
object.title = jsonDictionary[#"title"];
object.numericAttribute = [jsonDictionary[#"numericAttribute] integerValue];
If you take care about naming the attribute and entity names exactly the same you can maybe use some shortcuts using KVC, like
[object setValue:jsonDictionary[key] forKey:key];
I once did the above for a large legacy project where it was not feasible to repeat the old attribute names, so I used a custom property list (plist) to match around 800 attribute names.

Store a session information - one more Core Data table or separate session-file in "key-value" format (YAML, JSON)?

I have a Session class which I want to hold and store app's current session information (like lastLocation, remoteSessionToken, ...)
I have default Core Data setup with a bunch of tables and the most obvious solution I see is to create one more table "session" with two string fields: 'field' and 'value' and store session information to this table in way like I store any information to other tables
'field' 'value'
lastLocation 46.68,34.18
removeSessionToken au987asdv7tta487tv9b
...
Also, I know I could have this done using a special separate file for settings fx in YAML or JSON format but this would lead to a logical inconsistency with having both Core Data database and a file.
Is there any recommended approach for holding and persisting session information?
Unless something like the following applies, put it in user defaults or in a special purpose file in the documents directory:
You have many sessions and need to search or filter them based on some kind of predicate
You have more than one session and sessions have some kind of relationship to specific objects in the data store.
It's not a "logical inconsistency" to use Core Data and separate files. Do what makes sense. It's not likely to make sense to keep this information in your data store, so don't do it unless you have some compelling reason.
If the information could be considered sensitive, put it in the keychain.
Also, it's extremely ugly to create a generic container entity in Core Data. Using field and value fields like you describe is not a good design decision.
As long as it's not sensitive information, I would be consistent and use Core Data. A more obscure place would be to put it in NSUserDefaults.

Resources