How to get the actual quota for CloudKit? - cloudkit

Im using Cloudkit and the private database to store some files to iCloud and sync between iOS und OSX.
Now I wanted to implement something, the user can see how much space is left in his iCloud without leaving the app and look in the preferences. But I cant't find any information how to get this data. The whole CloutKit Framework reference has no object or method that gives me this information.
Because the private database uses the normal iCloud quota of the user, I could work around by looking for this data over any other iCloud API.
Anybody has an hint for me or a way to get this infos?

There isn't currently a way to get the remaining quota for a user in the private database at this time, so your best option is to just try to upload the data you want and watch for a CKErrorQuotaExceeded error.

Related

How to use sharing with CoreData/CloudKit synching

I have an app that works well synchronizing the local core data records with a private database. I would like to make the CloudKit database a shared database and then selectively share records with users. Is this even possible.
In other words, I'd like to continue having the Core Data/CloudKit sync working, but with the records that get synched limited to the user's share(s).
Does anyone have examples or a link to a discussion of this?
Apple solved this last year at WWDC21
Here is a link to the video
https://developers.apple.com/videos/play/wwdc2021/10015/
and some useful example code:
https://github.com/delawaremathguy/CoreDataCloudKitShare

FInd Out if User Switched off Document and Data From iCloud Account

Once again stuck in iCloud :(. I am using Core Data + iCloud and in my app i want to know if user switched off Document and Data from his account.
Thanks
There is no built-in support for detecting this change, only for detecting if the user has logged out. One common approach is to write a sentinel file to iCloud, separately from Core Data, and then monitor that file to see if it disappears. Details vary but it's usually something like:
Write the file using NSFileManager iCloud calls, and store the file name in user defaults. Each device using the account will have a different file, so including a UUID in the file name is a good idea. You only write this file, you never change it.
Use either NSFilePresenter or NSMetadataQuery to get notified of changes to that file-- like, if it disappears.
If the file disappears, take immediate steps to unload the entire Core Data stack, including every managed object, because they don't have a persistent store backing them up any more.
One sample implementation is in Black Pixel's version of the Core Data "Recipes" demo app. You might need to tweak it to get it to work right in your code.
There are two cases:
The app is not running, or in the background when the account status changes.
The solution here is to store / compare the identity token using NSUserDefaults (or some other storage local to the app). Grab the identity token from NSFileManager and compare it to the cached value each time the app finishes launching or comes back to the foreground.
id token = [[NSFileManager defaultManager] ubiquityIdentityToken];
The app is running when the account changes.
This requires a file presenter to "something" inside the container. The best solution is to use a file that is not synced.
Implement -accommodatePresentedItemDeletionWithCompletionHandler: to spawn a thread (dispatch_async works great) and do your cleanup work.

Whatever happens to iOS Application's data persistence when the App gets deleted?

I want to keep some of the critical(and less memory consuming) data of my App(ex: licence key or user credentials), stored in the device. In normal scenario, when the user deletes the App from the device, all the data related to the particular App gets deleted.
But I would like to override this behavior, and store some important stuff inside the device's disk, so that it does not get deleted along with the App. How to do that? Any help is much appreciated.
you can always store the license key and user credentials in the ios keychain.. it will stay there even if you delete the app. You can use the SSKeyChain API to access the key chain. Keep in mind you can only trivial string info this way.
Hopefully for obvious reasons that isn't possible. (What if every app did that? They you'd delete every app on your device and still find that gigabytes of space were being taken up by "deleted" apps.)
No, if you want data to be saved even after deletion, you'd need to store it in "the cloud" somewhere.

Retro-fitting my app for iCloud

I have been puzzling about retrofitting my app for iCloud for a few days and hope someone can help. After getting past code signing issues I am not sure I understand the model for incorporating iCloud. I'll tell you the problem I'm trying to solve first since I'm a big believer in telling people what I'm trying to do before having them try to fix the way I'm doing it :-)
My app workflow
User browses the store which lists a series of training plans they can download
User picks a plan and downloads it
I pull the training plan from our webserver customized to their needs
I add the filename for the training plan they downloaded to a plist of plans they own
User opens the training plan and sees the day-to-day schedule
I want the user to be able to do this on their iPhone and then open their iPad and see the exact same training plans synced over there.
My problem
I currently save the files to the Documents directory and that works just fine. How do I retrofit this to work with iCloud such that folks without iCloud enabled can continue to use the app but those who do get the added benefit?
My understanding
I'm confused as to whether I still need to save to Documents folder and then save a copy to the iCloud folder OR whether I just write to the iCloud folder from now on.
If it's the former I believe I just write a copy the Documents folder files to the iCloud area too to push it up but how do I detect a new file in the iCloud folder and copy it back to my Documents folder?
If it's the latter the files should just exist right?
I'm hoping it's the latter and that still supports devices without iCloud turned on...
Thanks for any help clarifying.
Adam
The iCloud API is pretty well documented and there is a specific chapter that deals with what you are after:
Managing the Life Cycle of a Document
A document goes through a typical life cycle. A document-based
application is responsible for managing its progress through that
cycle. As you can see from the following list, most of these
life-cycle events are initiated by the user:
The user first creates a document.
The user opens an existing document and the application displays it in the document’s view or views.
The user edits the document. A user may ask to put a document in iCloud storage or may request the removal of a document from iCloud storage.
During editing, saving, or other actions, errors or conflicts can happen; the application should learn about these errors and conflicts and either attempt to handle them or inform the user.
The user closes a selected document. The user deletes an existing document. The following sections discuss the procedures a document-based application must complete for these life-cycle operations.
In essence, you application is responsible for working out whether iCloud is available for a particular user and then confirm that the user wants to store their data in the cloud. Based on that selection you will need to work out how to move their existing data from the documents directory to a cloud URL.
On other devices that are setup to use iCloud storage, you have the option to discover documents available via a metadata query.
http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/DocumentBasedAppPGiOS/ManageDocumentLifeCycle/ManageDocumentLifeCycle.html#//apple_ref/doc/uid/TP40011149-CH4-SW1
If you are looking for a very easy sample which implements iCloud, have a look at this:
iCloud basics and code sample
This gives you a concrete example of how to implement some of the stages Rog has cited in his post above. Hope this helps.

on-the-device database for my iphone app

I want to have on-the-device database for my iphone app. It concerns with the data, which comes from dictionary consisting of 200.000 things and their definitions. It is only related with text-type data as appeared. My questions:
1- Does SQLite hold all of these data?
2- When the client downloaded my app, he/she will also have the db in his/her device. Does app store allow me to update my app's db and upload my new release? (i don't know these issues well by the way)
3- And can any client, who downloaded my app, hack and obtain my database? Is there any prevention methods? Is SQLite resilient enough against these?
1- Does SQLite hold all of these data?
Yes, SQLite can cope with this amount of data.
2- When the client downloaded my app,
he/she will also have the db in
his/her device. Does app store allow
me to update my app's db and upload my
new release? (i don't know these
issues well by the way)
The general approach is to store the SQLite database in your application bundle and then copy the database into the application's document directory on the device when the application is first run. On subsequent updates to your applciation, you should check if the database within the document directory is the same version and update it if necessary. See the existing Run NSBundle from the documents folder question/answer for more information on this.
3- And can any client, who downloaded
my app, hack and obtain my database?
Is there any prevention methods? Is
SQLite resilient enough against these?
It's fairly trivial to open up an app (the deployment package is just a zip file after all), so yes, it will be possible to obtain access to your database data. Unfortunately there's no easy way around this that I'm aware of. (You could I suppose download the data from a server when you first run you app, but it'll still be accessible on a jailbroken device.)
Sometimes, you just have to bite the bullet and accept the fact that your data is going to be ripped off.
1) sqllite can definitely hold that amount of data.
2) You can put up an option of refreshing the database in your app. That can be used to sync the local db with the server copy. Updated db can also be added with the new version of the app.
3) You can encrypt your local db using SQLCipher for protecting your application db against hacks.