When an existing database is opened and simperium is started afterwards, existing entities are not loaded to the server. Only newly created entities are loaded.
Is it possible to add Simperium to an existing database and upload all not yet loaded entities to the server? I'm thinking about adding Simperium to an existing app where the current data has to be uploaded on first start.
This is intended to be supported (and has been done in the app Simplenote), but it's possible there is something not working.
When your app starts, do you see a log message that says "Simperium managing X MyEntity instances" for the existing entity that you expect Simperium to see? And does X match the number of existing objects in your database?
Simperium performs a validation step on startup. If any existing objects that are detected in your model as being SPManagedObject subclasses are lacking a valid simperiumKey, one will get created.
Currently this validation process isn't automatically saving the new keys that are generated. Have you tried to save your context after Simperium starts for the first time to see if that triggers an update?
Also, if it's helpful, there's an undocumented method called getSimperiumKeyFromLegacyKey that you can implement on your object subclasses if you have an existing unique ID that you'd like to preserve in Simperium during this validation process.
Related
We have three separate apps which are in same App Group and access the same CoreData store. Problem is that when I change something in item in NSOrderedSet from relationship in managed object, save go to another app where refresh is performed, changed data are not there.
We are using NSPersistentContainer and only one context in each app, container.newBackgroundContext() saved to property in singleton. For each app when app goes to BG save() is performed on that context and when app goes to FG refreshAllObjects() is called on the context.
When I change some basic attribute in managed object it is changed properly in another app. But when I change some property in item from NSSet which is a relationship on managed object this change is not visible in another app.
While I was debugging I tried to call fetch but it also provides only old data. Only when I called context.reset() and then fetch again it returns valid new data.
Problem is that I cannot use reset on whole context because I will lose all registered objects in app.
Is this valid behavior or bug that referenced objects changes are not applied when refreshAllObjects() is used?
Is there any way how to force fetch request to get data directly from the database and not cached one from context?
I found one solution to my problem. I was able to force fetch to fetch directly from persistence (not from context) by setting shouldRefreshRefetchedObjects property of NSFetchRequest to true.
I was not able to find a solution to just refresh already fetched objects - but this way I was able to get fresh data using new fetch at least.
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.
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 want to add tables/columns to a database during runtime.
Currently I'm using Core Data.
I know that there's a possibility to do so in XCode (add new data model version), but I definitely can't use that way, because I receive the database schema from a web service.
Is there any good possibility to run ddl commands during runtime when using Core Data, or is it just possible with directly using sqlite (or a wrapper/ormapper)?
If it's better to use a wrapper/ormapper please give me some suggestions about which should be used in this case.
Workflow should be:
start app
check if database is up to date
if new version of schema is available from a web service do DDL commands
continue with app workflow
PS: Please no answers which describe alternatives modifying the schema with XCode!
Can you modify the Core Data model at run time? Yes...but, it probably won't work the way you want it to work.
Core Data's API makes it possible to construct or modify every detail of a data model at run time. Xcode's model editor is a convenience, but you could skip it and do everything in code if you wanted. For example, NSEntityDescription's properties attribute (which covers both attributes and relationships) is writeable. You could create a new NSAttributeDescription and update the entity's properties to contain it. Bang, you just added a new attribute to the entity. Similarly, NSManagedObjectModel's entities property is writeable, so you could create a new NSEntityDescription and add it to the model. That gives you a new entity, created at run time.
But, and it's a big one: you can only do this before you load the data store. Once you load your persistent store, altering the model will throw an exception. When Core Data loads a persistent store, it compares the model file to the model used in the store file. They must match, and you can't do anything to change this fact after loading the store. Once you load the store, the model is fixed.
What's more, even if you modify your model before loading the persistent store, you can only load persistent stores that match the current version of the model-- unless, that is, you also write code to migrate the persistent store to the new model. How hard that is depends on the nature of the changes. At a minimum then, you would need to make any changes before loading previously saved data, and then also arrange to do model migration to update the persistent store to use the new model.
With Core Data the model (schema) and data are stored separately and matched up when the store is loaded. That's not how SQLite works internally but it's the approach that Core Data enforces.
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.