Use UIDocument or KVS when saving to iCloud? - iphone

I am working on an iOS app that I want to use iCloud for storing documents/presets.
As you can see in the screenshots its quite a simple solution I have now. I Simply archive a list of presets (title, description, expression, and source). What would be the best solution for storing those presets/documents in iCloud so you can continue your work on iPhone/iPad/ (Maybe even OS X)?
Inherit from UIDocument, or use KVS with NSUbiquitousKeyValueStore?
Thanks!

I would suggest NSUbiquitousKeyValueStore since you are not storing an actual document and more configuration setting, plus NSUbiquitousKeyValueStore has the auto synchronize with your app and iCloud that you don't have to worry about. Also this is basically free memory in iCloud that doesn't count against the users memory allocation on iCloud.
If you are storing things like images, Documents would be a better fit.
Good example here:
https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/UserDefaults/StoringPreferenceDatainiCloud/StoringPreferenceDatainiCloud.html#//apple_ref/doc/uid/10000059i-CH7

Related

Syncing data to iPad from iPhone

I want to sync data between iPhone and iPad. I am using core data and save the data in Documents of Document Container. Since Documents is backed up by both iTunes and iCloud. Since iCloud is deprecated in latest version of Xcode. Do I have to do anything else to sync data between these iOS devices?
Backups are not a sync mechanism. For one thing, backups are device specific. Data that gets backed up from someone's iPhone is not available to their iPad. There is no device-to-device data mixing through backups.
Putting the persistent store file in iCloud (via the iCloud file API) is not workable either. You can't just read/write the file in iCloud directly, you need to download the file first and later upload changes. Core Data isn't designed to work in that scenario. You might write code to do it, but the data would become corrupted almost immediately because Core Data isn't expecting you to mess with the persistent store like that.
If you want to sync data between devices, there are many options. Apple offers CloudKit, which is free and supported by Apple. Firebase is popular. Parse servers are still extremely common even though Parse itself is shutting down. Add to that Microsoft Azure and many, many others.

Are CFPreferences "across app" readable?

Are CFPreferences across iPhone app readable?
In other words, can I write a NSUserDefaults style preference to disk and have it be readable in another iPhone app, if, for example, I didn't write this app, and am working from a static library?
I fear the answer is No. Period. Full stop. Any thoughts?
No. Apps have their own sandbox; you cannot interact between them in the manner you describe. As of iOS4, inter-app communication is quite limited.
One workaround is to use the keychain for storing small amounts of shared data, but there are many limitations to this method. You have to use the same id between applications and that precludes you from using push notifications and other features.
Alternatively, you could support Dropbox or something similar and store the shared information on the internet.
Neither is a great solution.

how to synchronize coredata between devices?

i have an iphone app that uses coredata to store its contents. users often ask me if i could provide a way to sync data between their mobile devices (ipod/iphone/ipad). as of now, i have no idea on how to achieve this.
i found zsync, but this seems to depend on a osx version of the app (which i dont have). i also read about upcoming iclouds sync features, and it seems to be what i need - however i think its not possible to sync coredata contents, but text-based contents only (e.g. xml storage files). is this true?
another way i was thinking of was to abuse the eventkit api to sync via a user-provided calendar. since my app is mainly managing events, which can optionally be stored in a user-calendar (in addition to coredata storage), syncing through a calendar would seem good to me. however i think syncing might break, e.g. when the user chooses not to syncronize the whole calendar but only like 3 months in the devices settings/account settings.
anyone got an idea of how my approach should be like? any tips?
Syncing device to device (if that is what you are trying to achieve) can be quite tricky. You could implement your own discovery and data-transfer protocol and work something out that way, but it could be quite a bit of work.
Syncing device to server to device is a bit more straightforward, assuming that you already have a server with some form of registration/login system. Then you just need a way of communicating your current database state up to the server, and then back down again from the server to other devices. Again there is a fair bit of work involved in doing this, but at least the logic of working out which devices sync with which other devices and how they transfer data from one to the other is all implicit in the workings of the server.
As for iCloud, the programmatic content that you sync through it needs to be derived from UIDocument, so it will not help you with generic Core Data entities.
If you're looking for an out-of-the-box solution that will sync all of your Core Data content from one device to another with no custom code, then there really isn't one. The closest you can reasonably get would be to ship the entire .sqlite file that your app uses from one device to another, overwriting the target devices .sqlite file. That works fine if your sync only needs to be unidirectional, but obviously is not appropriate for other use-cases. Perhaps you could use this model with iCloud, if you can get it to sync your app's entire .sqlite file as an atomic entity.

iPhone programming: How much data can I store in my app's Documents Directory (root folder)?

The reason I ask is my app lets users cache map tiles. Does anyone know the real cap on how much data I can let them store?
You can store as much as you want until you run out flash. Having said that, your users probably won't like it if you start eating all of the space on the phone.
Also, make sure you put it in the Cache folder, as opposed to Documents. The Documents folder gets backed up when you sync to iTunes, the Cache folder is not. If you have a ton of data in the Documents folder it will massively slow down iTunes synching.
About a year ago the word was there is a 2Gb limit on app size, but you'll be hard pressed to find an "official" declaration of such, even on apple's site or the discussion forums there
That being said 2Gb is pretty hearty for a mobile app, caching and all
I'm not aware of any quota for apps using the writable area, but it would be easy enough to check.

Do NSUserDefaults persist through an Update to an app in the Appstore?

Is this the case? Do NSUserDefaults get reset when you submit an update to an app on the App Store, or are they reset?
My app is crashing when updated but not crashing when downloaded fully - so I'm trying to determine what could possibly be different in the updated session to the freshly downloaded session.
Cheers,
Nick.
They are usually not reset unless the user deletes the app. For basic data, NSUserDefaults is the best way to save data such as preferences, dates, strings etc. If you are looking to save images and files, the file system is a better bet.
I beleive the answer is YES, it will persist. This also fully documented under the Application Directory chapter in the Apple iPhone OS Programming Guide.
Direct answer to the posted question: YES.
Your problem:
Your app gets crashed due to logic issues. Suppose you store an object in defaults and the app checks it's value on launch (or elsewhere). In you update you could change the way it is checked or used, e.g. you expect a value, but the object is nil, or vice versa. This may cause a SIGABRT or EXC_BAD_ACCESS.
If you had CoreData model and you changed something in your model and update, without managing migration, thats probably reason why your app crashes on update...
I have a similar experience. Our app stores a version number in Settings.Bundle/Root.Plist. This gets displayed through the iPhone Settings app. What we find is that on an Install the version number gets loaded from the app bundle - therefore the version number is correct. On an update however the version number doesn't change. This gives the impression the user is running a previous version of the app. We don't have any logic linked to the version number, it's just for display (it could be used by contact centre staff when diagnosing faults).
Our experience is NSUserDefaults doesn't get cleared when a user updates our app, but the Settings display doesn't get updated either.
Be aware of this case, when your app is running in background and you cannot access your stored values in NSUserDefaults:
Eric:
There have been many threads and bugs about this, but it's happening to me again in ios 9. I have an app that launches in the background in response to NSURLSession tasks and content-available pushes. Reproducibly, if I reboot my phone and wait for a background launch of my app to happen, then when I open the app I find that [[NSUserDefaults standardUserDefaults] dictionaryRepresentation] contains all the system values, e.g. AppleITunesStoreItemKinds, etc. but does not contain any of the values I have set. If I force-quit and relaunch the app all of my values come back. Is there any way to avoid it caching the "empty" standardUserDefaults from before the phone is unlocked, or at least to determine when they are messed up and fix them without having to force-quit the app?
Eskimo (eskimo1#apple.com):
The problem here is that NSUserDefaults is ultimately backed by a file in your app’s container and your app’s container is subject to data protection. If you do nothing special then, on iOS 7 and later, your container uses NSFileProtectionCompleteUntilFirstUserAuthentication, a value that’s inherited by the NSUserDefaults backing store, and so you can’t access it prior to first unlock.
IMO the best way around this is to avoid NSUserDefaults for stuff that you rely on in code paths that can execute in the background. Instead store those settings in your own preferences file, one whose data protection you can explicitly manage (in this case that means ‘set to NSFileProtectionNone’).
There are two problems with NSUserDefaults in a data protection context:
Its a fully abstract API: the presence and location of its backing store is not considered part of that API, so you can’t explicitly manage its data protection.
Note On recent versions of OS X NSUserDefaults is managed by a daemon and folks who try to manipulate its backing store directly have run into problems. It’s easy to imagine the same sort of thing coming to iOS at some point.
Even if changing the data protection were possible, NSUserDefaults has no mechanism to classify data based on the context in which you’re using it; it’s an ‘all or nothing’ API. In your case you don’t want to remove protection from all of your user defaults, just those that you need to access in the background before first unlock.
Finally, if any of this data is truly sensitive, you should put it in the keychain. Notably, the keychain does have the ability to set data protection on an item-by-item basis.
Source:
https://webcache.googleusercontent.com/search?q=cache:sR9eZNHpZtwJ:https://forums.developer.apple.com/thread/15685