I have an app which has different app identifier for iphone and ipad and i want to sync both of them using icloud, is it posible to use different app identifer for same container in icloud.
Yes, it is possible to sync data between different apps using iCloud (different apps always have different app IDs, don't they?). Use the entitlements of your apps to specify to which containers they should have access. Then use a common container to store and sync your files.
Update on 10/30/2013 on request of Dinesh Kaushik:
Open your project in Xcode and select the project in the ProjectNavigator
Go to the "Capabilities" Tap (Xcode 5) of the project and find the iCloud section (should be right on the top)
Here you can specify all Ubiquity Container the app should have access to.
To share data between apps they need to share a common Ubiquity Container. Thus add at least one Ubiquity Container that is used by
all participating apps. The easiest way to just one Ubiquity
Container (of course the same in each app)
When "connecting" to iCloud you use the following code to get the Ubiquity URL:
NSURL *cloudURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
Using nil as identifier will return the URL of the default Ubiquity Container. Use a concrete ID to get the URL of another Ubiquity Container.
The Ubiquity Container is basically just a folder on your device. The iCloud Service will observe this folder and transfer all changes to the same folder on other devices.
From my experience there is one golden rule about iCloud:
DONT USE IT!
I am serious. iCloud is unstable and unreliable. Your app might crash from time to time and you will never find out the concrete source of the problem. Users will ask why syncing does not work from time to time and blame you and your app for the poor performance.
iCloud might be OK for simple KeyValueStore but anything else is a mess. Do not wast your time. Use another Cloud service like Dropbox instead.
Related
Can you, in Swift get a change notification when a document in the apps's iCloud Drive container changes?
For example I am testing a simple concept where I am storing all app data as a json string in the app's iCloud Drive container and I am loading it when the app launches. I can retrieve and save the json string on demand on multiple devices, but I am wondering if there is a way to get a change notification sent to an app when the file is changed on another device.
If so, some direction would be appreciated.
If you are using UIDocument, you can register for UIDocumentStateChangedNotification (for a particular document), otherwise if you are looking for changes in the App's iCloud container you need to use NSMetaDataQuery which is described in Discovering an App's Documents in Document-Based App Programming Guide for iOS
So my question is as written in the title if you could use NSPersistentCloudKitContainer to share data between different apps like if you have a different app for iPad, a different one for iPhone and a different one for Mac and if possible how would you do that?
Thanks in advance!
Yes, you can, even across different platforms (macOS, iOS). I have done that several times, actually. All it takes is the same iCloud bundle ID. Click on Capability to select iCloud. Turn on the CloudKit checkbox button. Then select a specific bundle ID below.
If you are going to use the same cloud container, you must be careful with the data types you use. For example, you shouldn't save UIImage or NSImage there because they are not exactly compatible with each other. In this case, you should save an image as Data.
Addition
When you want to use a specific cloud container other than the (default) one that your project has automatically created, make sure you specify it in accessing the cloud database. That's the same for macOS and iOS.
let cloudContainer = CKContainer(identifier: "iCloud.com.tomato.Eltomato")
let publicDB = cloudContainer.publicCloudDatabase
I got a project like MyPhoto Pro app in iPhone App Store (website).
Please, can any one help or guide me what are the technologies and frameworks i should use for developing?
But my primary things is that image should stored in iCloud.
For iCloud file storage see Designing for Documents in iCloud in docs.
Then check NSFileManager class, section Managing ICloud-Based Items.
-ubiquityIdentityToken – detect iCloud availability
-URLForUbiquityContainerIdentifier: – obtain URL for iCloud directory (container)
-setUbiquitous:itemAtURL:destinationURL:error: – move any local file to iCloud (or vice versa); one URL must be local and one must point into one of the iCloud containers
-startDownloadingUbiquitousItemAtURL:error: – download the file content
-evictUbiquitousItemAtURL:error: – delete iCloud file.
Also check NSMetadataQuery and NSMetadataItem classes used to discover new iCloud files. iCloud will automatically give you only metadata of the file, but content must be downloaded explicitely (see the methods above)
If a user installs an an app which uses iCloud with a UI(Managed)Document, then uses the app, creates data which is saved to iCloud and then deletes the app on his phone, the iCloud data will stay on the device (transaction logs etc.). If the user reinstalls the app it will try to use these old files.
I have the following two problems with that:
The iCloud documents could have changed in the meanwhile and there might be problems when the user has no network connection on the first launch after reinstalling the app.
The iCloud documents for this app could have been deleted by the user (via settings or in Mac OS Finder in the user library). Now, when the user has no network on the first launch after reinstalling the app, the app might think that there is an ubiquity container with data even though it's already deleted (app might crash).
This is not very easy to test but I have definetely crashes and malfunctions for those two issues. E.g. NSMetadataQuery shows me results for documents which do not exist in iCloud because they have been deleted (but they existed on the deletion of the app).
Is there any easy solution to this? I thought about deleting the local iCloud data on the device when the app is launched for the first time - but how can this be done?
It can't be done. If you delete an iCloud document locally, you delete it everywhere-- eventually. The iCloud APIs have no concept of managing local copies independently of the iCloud service, so if you delete one-- even with the network down-- the iCloud ubiquity daemon will send a delete command to the service at the first opportunity.
The closest approximation that current APIs would allow would be:
Check whether the network is reachable
If it's not reachable, do not attempt to access any iCloud documents (because as you note, the information might be stale).
If and when the network comes up, try to open all existing iCloud documents. (On iOS, iCloud updates are only downloaded on demand, so you need to create that demand).
If that's not good enough (and let's face it, it's not good enough), file a bug with Apple and hope for the best.
For example, is it possible the storage container key in the entitlements dictionary would accept "*" or "/", allowing me to access any and all data in that user's iCloud?
I am not worried about getting this app accepted into the app store.
No.
And, even if you could, there wouldn't be any way to enumerate that data. -[NSFileManager URLForUbiquityContainerIdentifier:] and friends require you to know the containers you want to access. (You can pass nil, but that just returns the first container you have access to, not some parent of all containers.)
And this is intentional. The public APIs aren't meant to let your app interfere with other apps' storage (except for related apps that share a team), for pretty good reasons. You may want to read iCloud Storage in Mac App Programming Guide (which doesn't require a paid membership to access).
So, how does the iCloud preference pane do it? Well, that's a secret. Presumably it either uses private APIs, or just talks to the iCloud web service directly in a way that the APIs can't. You could presumably reverse-engineer it, but that's the only way you'll be able to do this.