I am using RestKit to download data from an API, namely an array of book descriptions. In my app, this data is read-only. I need that the user can mark some of the items downloaded as favourites.
I would like to save this bookmarks also in Core Data in a way that permits to use a NSPredicate to fetch only favourite books.
I can't just add a favourite field in the books entity because its value would be overwritten each time the app downloads data from server. I guess I need a different entity and I must establish a relationship between them but I couldn't find the right way.
How could I address this? Thanks for your help.
Each of your books must have an identifier property. Simply create a list of the identifiers of the favourite books. You probably don't even want to store this in Core Data. Instead, store it in an NSArray and store it in NSUserDefaults.
Related
My app uses local iOS contacts together with some server contacts in the same list.
Server contacts are fetched on startup and saved in NSManagedObjectContext.
Each server contact is represented with Contact class which is subclass of NSManagedObject.
Local contacts I fetch with CNContactStore.
The problem is how to handle this "joining" into single list.
What comes into my mind is:
1.) Save both server and local contacts into same NSManagedObjectContext as Contact objects, and fetch it from there.
-> pros: - fetching is unified
-> cons: - local contacts are doubled in store memory
- if user adds new local contact out of our app, it will not be automatically shown in list
2.) Save only server contacts, and every time user goes to contact list fetch local contacts, and append it to list
pros: - contacts are saved only once, local contact updates are always shown
cons - fetching is not single source, and this complicates things with using NSFetchResultController
Maybe there is some other way?
So, what would be best way to show in the same list cached server contacts and local iOS contacts?
If it were me, I'd prefer to keep these two groups of contacts separate rather than combine them in one list. Provide some UI so the user can select their device's contacts database or your app's database, and handle CNContact separately from NSManagedObject.
If that's not possible (or just not appealing), I'd do something like
Save only server contacts in my Core Data store.
Design my NSManagedObject subclass to have a transient property of type CNMutableContact. Any time I fetch one of the server contacts, I can get a contacts-style object for it without saving it to the user's contacts database.
Fetch all of my server contacts from Core Data, and all of the CNContact instances from CNContactStore, and merge the results into one array using the property from step 2.
Display that array. This would, of course, mean not using NSFetchedResultsController, but that's life.
You might want to subclass CNMutableContact as well, to add a property that would store the NSManagedObjectID of the managed object that created it. Then if the user edits the contact info (if that's allowed) you can use that to find out which managed object you need to change.
iOS newb building an app to work with a website. Ultimately, I want to keep the app and backend on the website in sync.
Photos are saved on the website using the ID of the item. For the app, I would also like to save the photo with a unique number linked to the item.
On the website, the id of each item is simply the auto incremented number in a MYSQL table.
My understanding is autoincrementation is impossible in Core Data but it does create unique identifiers for each managed object.
How would I get and store this number in the core data database at the time the item is created for later retrieval?
Alternatively has anyone discovered a way to auto-increment in core data so as to give items numbers that could be used for storing photos. It would be nice to have a similar naming scheme for photos created by the app and those created through the website.
There is no 'built in' solution for creating an auto-incrementing id in Core Data.
One important thing you should recognize is that Core Data is an object graph not a relational database. This is very important in understanding how you should approach design with Core Data.
Yes, Core Data does create unique identifiers for objects in the form of GUIDs - so it's not a number, but rather 32 hexadecimal digits (Globally unigue identifier).
You can write a method that will get the next number in a sequence for an entity, but Core Data will not do it for you.
You may find the information in this question useful: Set auto increment in Core data iOS. I would not attempt to use NSManagedObjectID. This value can change.
My suggestion is that you allow the MySQL database to assign the id's and simply store that id in a number property in the Core Data object. For items originating in the app leave the id property blank until it has been sent to the MySQL database for persistence. Then, retrieve the Id that the database assigned it and set it to the Core Data object's property.
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.
I have some data that needs to be loaded from the server (backend). For example, let's just say I have an entities of user and event. The relationship between them is many-to-many (user can attend many events and event can have many attendees). All the data is stored remotely on backend and locally in Core Data. When I download data from backend I convert it into NSManagedObjects and store it in NSManagedObjectContext. Everything's very simple, but...
When I download a list of events I want to know, how many attendees this event has. But I cannot download a list of users in the same request, because it's totally overkill. What I need is to download, let's say, a list of users' unique ids so that I can have two things: total number of attendees and means to download detailed data of concrete users (via unique id). Or there's another example: I need to know total number of attendees and download a limited set of them, so I can create some entities in CoreData, but not all of them.
So the main question is how am I supposed to store such information in my CoreData? Meaning I need to know that for some entity there are some related entities in relationship that are not actually currently present in CoreData, but I know how many of them there should be. The first thing that came in my mind is to have a attribute called something like usersCount in my event entity, but that seems to be kind of dirty. What is the best practice for such situation?
Please comment if the question is not clear enough so I can maybe add some more specifics.
When you download an event with a list of corresponding user ids, then you can create
the Event object and also the related User objects, but you fill only the "userId"
attribute in the user object.
Later, when you download the complete user info, you update the existing (incomplete) objects
or create new user objects. Implementing Find-or-Create Efficiently in the "Core Data Programming Guide"
describes a pattern that might be useful.
So the idea is to create Core Data objects with incomplete information first and update the
objects with detailed information later. The advantage is that you can set up all relationships immediatly, and e.g. counting related users works even if the user information
is yet incomplete.
There is nothing dirty about having an attribute to store the count, especially if those entities are retrieved and paged via separate requests.
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.