So I do alot of fetching of my objects. At startup for instance I set an unread count for the badge on a tab. To get this unread count I need to fetch my datamodel objects to see which objects have the flag unread. So there we have a fetch. Then right after that method I do another fetch of all my datamodel objects to do something else. And then on the view controller I need to display my datamodel objects so I do another fetch there and so on.
So there are alot of calls like this : NSArray *dataModelObjects = [moc executeFetchRequest:request error:&error];
This seems kind of redundant to me? Since I will be working alot with my datamodel objects can I not just fetch them once in the application and access them through an instance variable whenever I need to access them? But I always want to have up-to-date data. So there can be added and/or deleted datamodel objects.
Am I making any sense on what I want to achieve here?
On of the concepts and benefits of Core Data is that you don't need to access the database every time you need an object - that's why NSManagedObjectContext was created - it stores those objects, retrieved from the database, so if you will try to get the object you've already get fromt the database, it wil be really fast.
And every change in those objects, made in the NSManagedObjectContext are automaticly brought to you.
But if you had some changes in the database, they may not be reflected in the NSManagedObjectContext, so you'll have to refresh them. You can read about keeping objects up-to-date here.
Related
In my CouchDB database I'd like all documents to have an 'updated_at' timestamp added when they're changed (and have this enforced).
I can't modify the document with validation functions
updates functions won't run unless they're called specifically (so it'd be possible to update the document and not call the specific update function)
How should I go about implementing this?
There is no way to do this now without triggering _update handlers. This is nice idea to track documents changing time, but it faces problems with replications.
Replications are working on top of public API and this means that:
In case of enforcing such trigger you'll have replications broken since it will be impossible to sync data as it is without document modification. Since document get modified, he receives new revision which may easily lead to dead loop if you replicate data from database A to B and B to A in continuous mode.
In other case when replications are fixed there will be always way to workaround your trigger.
I can suggest one work around - you can create a view which emits a current date as a key (or a part of it):
function( doc ){
emit( new Date, null );
}
This will assign current dates to all documents as soon as the view generation gets triggered (which happens after first request to it) and will reassign new dates on each update of a specific document.
Although the above should solve your issue, I would advice against using it for the reasons already explained by Kxepal: if you're on a replicated network, each node will assign its own dates. So taking this into account, the best I can recommend is to solve the issue on the client side and just post the documents with a date already embedded.
I'm currently re-factoring an Android project that in a few places loads data on background threads in order to update list views. The API that is being called to collect the data has a callback mechanism, so when a lot of data is returned (which takes a long time) I can handle the results asynchronously.
In the old code, this data was packaged up as an appropriate object and passed into a handle on the UI thread, to be inserted into the list view's adapter. This worked well, but I've decided that presenting the data through a ContentProvider would make the project easier to maintain and expand.
This means I need to provide the data as a Cursor object when requested via the query method.
So far I've been unable to update the data in the Cursor after retuning it. Does this mean that all of the data needs to be collected before returning the Cursor? The Android LoaderThrottleSupport sample suggests that I don't, but I have yet to get it working for anything other than an SQL backend.
Has anyone else tried to present non-SQL backed asynchronous data in this sort of way?
Whenever a document is accessed, I would like to add last access time into the document.
How do I update a document in a view whenever there is GET request?
You can't. A GET (when used correctly) does not modify data; CouchDB uses GET correctly.
If you really want to record an access time like this you'll need to update the document with the new timestamp and PUT the document back to CouchDB. However, if more than a few people are accessing a document you're quite likely to get contention over it and get conflict errors from CouchDB.
One option is to create a new "document accessed" document in CouchDB on each access but that would rapidly increase the size of the database. You'd actually have a history of access times if that's useful?
Personally, I would look at simply logging document access to a file or queue and process the file/queue in the background. You could have one "document accessed" document per real document as there's little or no chance of contention and a failed update probably wouldn't really matter (you could always try again anyway).
Is there way to limit the number of saved objects in coredata like stack, where the last objects are automatically deleted?
No, that is something you would need to implement in code. You can, just before you call -save: on the NSManagedObjectContext query the NSManagedObjectContext for how many objects are going to be inserted and perform your custom logic at that point.
I'm converting an app from SQLitePersistentObjects to CoreData.
In the app, have a class that I generate many* instances of from an XML file retrieved from my server. The UI can trigger actions that will require me to save some* of those objects until the next invocation of the app.
Other than having a single NSManagedObjectContext for each of these objects (shared only with their subservient objects which can include blobs). I can't see a way how I can have fine grained control (i.e. at the object level) over which objects are persisted. If I try and have a single context for all newly created objects, I get an exception when I try to move one of my objects to a new context so I can persist it on ots own. I'm guessing this is because the objects it owns are left in the 'old' context.
The other option I see is to have a single context, persist all my objects and then delete the ones I don't need later - this feels like it's going to be hitting the database too much but maybe CoreData does magic.
So:
Am I missing something basic about the way my CoreData app should be architected?
Is having a context per object a good design pattern?
Is there a better way to move objects between contexts to avoid 2?
* where "many" means "tens, maybe hundreds, not thousands" and "some" is at least one order of magnitude less than "many"
Also cross posted to the Apple forums.
Core Data is really not an object persistence framework. It is an object graph management framework that just happens to be able to persist that graph to disk (see this previous SO answer for more info). So trying to use Core Data to persist just some of the objects in an object graph is going to be working against the grain. Core Data would much rather manage the entire graph of all objects that you're going to create. So, the options are not perfect, but I see several (including some you mentioned):
You could create all the objects in the Core Data context, then delete the ones you don't want to save. Until you save the context, everything is in-memory so there won't be any "going back to the database" as you suggest. Even after saving to disk, Core Data is very good at caching instances in the contexts' row cache and there is surprisingly little overhead to just letting it do its thing and not worrying about what's on disk and what's in memory.
If you can create all the objects first, then do all the processing in-memory before deciding which objects to save, you can create a single NSManagedObjectContext with a persistent store coordinator having only an in-memory persistent store. When you decide which objects to save, you can then add a persistent (XML/binary/SQLite) store to the persistent store coordinator, assign the objects you want to save to that store (using the context's (void)assignObject:(id)object toPersistentStore:(NSPersistentStore *)store) and then save the context.
You could create all the objects outside of Core Data, then copy the objects to-be-saved into a Core Data context.
You can create all the objects in a single in-memory context and write your own methods to copy those objects' properties and relationships to a new context to save just the instances you want. Unless the entities in your model have many relationships, this isn't that hard (see this page for tips on migrating objects from one store to an other using a multi-pass approach; it describes the technique in the context of versioning managed object models and is no longer needed in 10.5 for that purpose, but the technique would apply to your use case as well).
Personally, I would go with option 1 -- let Core Data do its thing, including managing deletions from your object graph.