RESTkit, CoreData: process object right before trasferring it to CoreData - ios

I have a problem.
I have iOS client app that has to allow multiple users to log in and store their data locally.
Data is synchronized with RESTful service, and the latest snapshot along with user's changes should be stored locally for all users.
Previously this app was implemented with SQLlite as data storage engine.
Now I would like to migrate to CoreData.
What do I have:
server returns me entities for current user. User ID is not sent, as the user authorizes and gets their session;
I know who is logged in an should store all data for this particular user. In order to do that I need to say CoreData to store the object for the user with ID=12345.
The problem is:
I have to tell CoreData to store the particular object associated with particular user's ID.
I need a way to somehow alter the object mapped with RESTkit - setting proper ID field for it.
This task was straight and simple with SQLlite but looks problematic with CoreData.
I am still thinking that I don't know something about CoreData asking you to help me with clarifications or useful links.

There isn't a good way to do it.
Hacky, you could add the id as a parameter in the request so you can map it back again (requires RestKit dev branch at time of writing).
Non-hacky is to update and re-save the objects returned in the mapping result.
Alternatively you could use one operation to download the JSON, then mutate it, then run another operation to map it.

Related

Core Data Values Accessed by Multiple Users when logged in (iOS Swift)

I have an app where a UITableView is used to represent a friends list. Now, this table is updated by values stored in core data, and I'm downloading friend values to core data via Parse. Instead of accessing Parse to update the tableView directly, I decided to update Core Data and then the tableView because I need the friend information in other parts of the app, and thought it would be more efficient to use Core Data than to have calls to Parse again and again. Everything works fine!
However, my app has a log in system before users can use the app. And when I created another dummy user to test it, I found that the friend values stored in Core Data by my actual account were being used to update the friend list tableView! When actually the tableView should be empty (new user).
I don't know exactly how Core Data works but I figure it uses some segment of the device's memory to store entities. My question is this, is it possible to use Core Data to store private information related to a particular user that can't be accessed by other users that log into the same device? Or should I continue to make calls to Parse whenever I need information?
Hope you guys understood my question, thanks!
iOS is not a multi-user system. Your app stores its files in a sandboxed folder structure and this sandbox is independent of any user logins you have implemented in your app.
When a new user logs in (or, if you prefer, when a user logs out) it is up to you to remove any data you have stored in Core Data that you don't want another user to have access to.
Parse can save data offline by Local Storage or cache the request by Cache Policy
They are much faster than creating your own database (by CoreData).

Parse's CurrentUser doesn't keep refreshed data

Using Parse for iOS, I modified the _User's table to have a field called "Friends" which is an array of pointers to other _Users (by the way, I also have other additional fields).
When I call PFUser.currentUser(), I don't see this friends field in the user object. So I call PFUser.currentUser().fetch() (because refresh method doesn't seem to exist anymore) and I finally have the friends field in my currentUser object.
However, as soon as I exit the app, this field is lost. It doesn't seem to be saved locally unlike all the other fields of the current user.
How am I supposed to force a refresh of the cached current user ?
According to parse.com itself and one of their posts, there is no other way to keep your user up-to-date:
saveEventually does not write through any caches at this time,
including the currentUser, if the app has been restarted. You'll need
to regularly call fetch to keep it up-to-date. We are aware that this
is inconvenient, and are looking into ways to make it work better for
you.
Are you sure that you want your user objects to contain a value that's an array like that? I obviously don't know your use application, but I would recommend using a PFRelation instead. It works just like an array, but the Parse Framework provides a bunch of additional functionality along with it.
As for your specific question it might have to deal with Parse. Maybe they don't automatically retrieve and save arrays that are on an object. That would be my guess because an array could contain who knows how much data in it. I still don't know why they wouldn't locally save that data after it's fetched.
My suggestion is probably a little over the top, but would most likely be the best outcome. Utilize a local database such as CoreData or even the ParseLocalDatastore. Then encapsulate the Parse framework to have your own User object where you can store the information, which can also maintain persistence via your database.

Strategy to have deleted objects in DB deleted in Core Data as well. [RestKit/Core Data]

I have a REST service running on top of my application, which returns data to my iPad app. This app is built using RestKit to sync data in and out of the iPad. I have however a webapp running as well, which allows the users to delete some data.
The current problem that I have right now, is that whenever a user logs in into the iPad app, I run a query to get the data that was last_modified/added since his last login. This allows me to have faster/shorter queries. The only problem, is that if for example an object was deleted from the DB between his last two logins, the user will still see it in his iPad.
What strategy should I adopt to have this data in Core Data deleted as well? Should I just not delete object from my DB and have instead a BOOL that says "deleted" or not, and whenever I get the last_modified data via REST, this item will appear and I will just filter it out in the iPad?
I know RestKit has a way to delete orphans objects, but since I am syncing the "last_modified" data, I don't think it can be applied here.
From your comment question:
I created a list of objects that needs to be deleted from CoreData. So for I example, I return an array of IDS that corresponds to the Users I need to delete in CoreData. How can I do such mapping with RestKit?!
You should create a mapping to NSMutableArray. If your source data is a JSON array of strings then you will need to use a nil key path mapping in order to get the strings extracted into your destination array. See this link.
As Wain suggested, I will have a list of deleted objects in the Database with a "deleted_date" field. Whenever I will fetch the latest objects, I will also fetch the latest deleted objects back.

Remote Server Searching in RestKit with Core Data

I have an application that talks to a remote API using RestKit with an SQLite store for Core Data. When I got to the point of adding server-side searching, I was faced with having to find a way to efficiently display search results. To accomplish this, I used an NSFetchedResultsController that is tied to another in-memory store of the same schema as the SQLite store, and also backed by RestKit. When RestKit searches against the API's search endpoint, it maps the responses back to the in-memory store.
This works really well for what I need, but has now caused another issue. When I get these "transient" objects back from the server, and the user selects one, it needs to be copied into the persistent store at that point (various interactions beyond that point will load additional objects from the server and attempt to tie them back to the original object - which will fail if they're in two different object contexts).
tl;dr
Does anyone have any suggestions on how to copy an entire object (entity and relations) from one core data store to another? Or, is that even necessary? Is there an easier way to accomplish this same task using RestKit?
Would I be better served by changing my search instead, to not use an in-memory store? If so, how should I store these objects?
I wouldn't use the in-memory store. I'd just put the search results into the main store and bypass the issues with copying. I'd then have a purge that ran to clean out the old search results that aren't required any more. You might want to tag search results that need to be kept around for some reason. And you can get RestKit to do the purge automatically when each new search is performed (see "Fetch Request Blocks and Deleting Orphaned Objects" in these docs)
For your other question, about tagging. When you make the search request, the search term is in the URL. If you use RKObjectManager and routing then you can access the metadata that is provided to the mapping to get the search term and store it into the returned objects. Something like:
#"#metadata.routing.parameters.searchTerm": #"searchTerm",
See the metadata docs here.

CoreData Update Database Leaving User Entries

First, Thank you for any help provided.
I have an iOS leveraging CoreData to retain various presentations, this data comes from a sqlite file and there is no server connection.
I will have to be able to provide App updates (via appstore), this update may add more data to the database.
The tricky part is that it can not simply overwrite the current database, there are a few user tables that I will not like touched.
Please provide any information I should consider when accomplishing this or any links are greatly appreciated.
Thank you.
Given your app has no server connection, you will have to rely on shipping data within the updated application itself. I would recommend using a plist file or define your own xml or json structure. You can then read this data to create/update core data nsmanagedobjects.
It looks like someone in the past was using plist->coredata on SO
Would you have relationships between user created data and shipped data?
If not, you might go the route of connecting two stored to the persistent store coordinator. The shipped store would be read-only. The store with user created data would be read-write. You can use this approach, too, if you have relationships between shipped and user-created objects, but it's a lot more complicated, since CoreData doesn't manage cross-store relationships for you, and you'll need to write your own logic (doable, but not straight forward).
If you need to have relationships between shipped and user-created objects, you can still ship a CoreData store. When the app launches for the first time (no user-created objects), you copy the store to the Documents folder and user this store to create your CoreData stack. User created objects will be added to this store. Once you have new 'shipped' objects (i.e. a new store in the app-bundle), you'll have to manually migrate that stores data into the store that the user has changed. You'll have to be able to find
(1) objects that need to be deleted
(2) objects that need to be updated (changed)
(3) objects that need to be added
If you mark your shipped objects with a special flag such that you can tell if it's a user created object or a shipped one, that would be doable. You also have to have some sort of ID to be able to tell which objects in the new store correspond to which ones in the existing (old) store.
You do not need to go the route of using plists. In fact, I'd recommend against it. You can easily open two stores at the same time. Either to use both stored, or just to migrate objects from one store to the other store.

Resources