Backup your application’s data with iCloud and track progress
Taking a backup on iCloud from your application and restoring the data at a later point of time may seem quite an easy task but unfortunately, I have seen many developers getting stuck and almost no detailed help is available on the internet. The purpose of writing this article is to help developers who spend a lot of time looking for solutions for a problem which ideally should be a fairly simple one.
What will you achieve by the end of this tutorial?
- Upload the application’s data on iCloud.
- Track the progress of the backup as it is uploaded to the iCloud.
- View the backup of your application in the iCloud directory on your iPhone.
You’ll be able to upload, track progress and also manage the backup data of your application from the iCloud directory on your iPhone.
Prerequisites for implementing the iCloud backup.
- A real iOS device. I am going to use an iPhone X with iOS13 but the actual minimum requirement is any real iOS device. This may work in an iOS simulator too but I have not tested in on a simulator at this point.
- An apple ID logged in to your iOS device, with enough space available for the backup of the application.
- An apple developer account with the capabilities of creating certificates and identifiers.
iCloud configuration and step by step implementation
Step 1, setup project: Let us start by creating a new Xcode project, we will create a single view application and name it iCloudBackup.
Hit Next and save the project anywhere on your Mac. If you already have an app identifier for your application, skip directly to Step 3.
Step 2, creating app identifier: Now, login into your apple developer account and go to Certificates, Identifiers & Profiles > Identifiers.
Click on ‘+’ to create a new identifier and select App IDs from the list that appears.
Hit Continue, and enter the Description as iCloud Backup and the bundle ID as com.backup as shown in the image below.
Hit Continue, then hit Register and a new app ID will be created in the list with the name of iCloud Backup. Now, that we have successfully created an identifier for our app, it’s time for us to now create an iCloud container and link it to our app ID.
Step 3, enabling an iCloud container for our app ID: Now, we are going to create an iCloud container for our application and link it our app ID. The iCloud container is specific to our app ID and it’ll be shown in the iCloud drive on our application. To create one, go to Certificates, Identifiers & Profiles > Identifiers on your apple developer account and hit ‘+’ to create a new identifier. From the list, select iCloud Containers and hit Continue. Enter the name as iCloudBackup Container and the identifier as iCloud.com.test.backup and hit Continue > Register, and a new container will be added to the list.
Step 4, registering your iCloud container with your app ID: Let us now link the newly created iCloud container with our app ID. Proceed to your apple developer account, and go to Certificates, Identifiers & Profiles > Identifiers. Click on your app ID to open it, in our case com.backup, it’ll show the list of Capabilities, enable iCloud and hit the Configure button right next to it to add your iCloud Container to the app ID.
This will open a list of your iCloud containers, select the one with identifier iCloud.com.test.backup, hit Continue and then hit Save. With this, the iCloud container is successfully added to your app identifier. Next, create a provisioning profile for your app identifier by going to Certificates, Identifiers & Profiles > Profiles. Creating profiles is not covered in this article, if you need help creating provisioning profiles, you refer to this article here.
Note:- If you added the iCloud container to an existing app ID for which you have existing provisioning profiles, you’ll need to regenerate those profiles as they’ll be rendered invalid after the addition of iCloud container.
Step 5, enabling iCloud capabilities in Xcode: Now, let’s move on to the Signing & Capabilities in your xcode Project and hit ‘+’, at the top left side on the section, to add a new capability. Double click iCloud from the list, and select iCloud Documents in Services and select the container we just created.
Now we are all set with the iCloud configuration and can jump to the actual coding. Hooray!
Step 6, some coding finally: Now, let us create a new file named, Backup.swift and add it to our project.
Create a new class Backup.swift and add an instance of NSMetadataQuery and an initialisation method in it. The query variable is used to start any operation on the iCloud, be it uploading or downloading.
Next, let us add a .mp4 file that we will upload to our iCloud container. You can download a sample .mp4 file from here. After you download the .mp4 file, simple drag and add it to your xcode project and rename the file to sample.mp4.
Then within the class add this function.
In the above block of code, we are simply initialising the query when the class is initialised. The operation queue to execute upon is .main, the search scope is NSMetadataQueryUbiquitousDataScope, which means that the file will reside within the Data directory on the iCloud container, and the predicate specifies to search for NSMetadataItemFSNameKey with value of sample.mp4 (the name of our mp4 file).
Next, we are going to add a function to our Backup class, to start uploading the file to iCloud.
The code written above is pretty much self explanatory. We have created a new function named startBackup(), which is a throwing function. Inside it, we have created a fileURL, which is the URL of our sample.mp4 file. Next, we created a containerURL, which is our iCloud container URL.
Note: A ubiquity container is an iCloud container for our app, and note that we have created this ubiquity container with the same identifier that we gave to our iCloud container in the apple developer website. If you pass different identifier here, the URL will return a nil value.
Subsequently, we check if the ubiquity container already exists, if not, we create a new one. Next, we check if our file already exists on the ubiquity container. If yes, we delete the old file and copy the new file to the path. If not, we simply copy the new file to the path.
Next, we fire the query on its operation queue and enable updates on it. The updates are enabled in order to track the progress of the upload.
Now that we have successfully initialised and fired our query to start uploading our sample.mp4 file to the iCloud container, it’s time for us to track the progress of the upload. We will be doing so by subscribing to the notifications that are posted by our NSMetadataQuery instance (i.e. query).
Step 7, tracking progress of upload: In the above steps, we have successfully configured the iCloud container for our app, enabled it, and initialised the upload of a sample video file. Next, we are going to track the progress and completion of our file upload.
For this, let us add observers to listen for the updates thrown out by the query. Add the below function in your code.
Don’t forget to call this function from the init method of your class.
override init() {super.init()
initialiseQuery()
addNotificationObservers()
}
Here, we are adding notification observers named NSMetadataQueryDidStartGathering and NSMetadataQueryDidUpdate. The first one lets us know when the query has started gathering information about the upload operation and the next one lets us know the query has some update available for us.
Next, let’s add the processCloudFiles() function in our code to complete the progress tracking of the file.
In the above code snippet, we are iterating the results of the query and extracting a NSMetadataItem and a URL for our file upload. Once we have both of these, we are checking to extracting the resourceValues on our fileURL, and checking to see if the item is uploading or not by checking its ubiquitousItemIsUploading property. On our fileItem, which is an instance of NSMetadataItem, we are checking the value of its NSMetadataUbiquitousItemIsUploadedKey attribute, which lets us know if the file is uploaded to the iCloud drive or not.
To further check for any errors, we are checking for ubiquitousItemUploadingError on the fileURL’s resourceValues.
Finally, to get the progress of the upload, we are checking the NSMetadataUbiquitousItemPercentUploadedKey attribute of the fileItem, which gives us the value of the upload progress.
That is all we need to do in order to do in order to start the upload and get its progress. Now let’s add a dummy button, named Upload to iCloud, in our ViewController.swift file and add an action to it.
All is set now. Let’s go ahead and run the code and see if everything is working as expected.
If you have followed the code step by step, you’ll be able to see the following output in your console.
Further, to verify if the file has actually been stored in our iCloud drive, let’s move over on your iPhone to Settings. Tap on your name on the top and then go to iCloud > Manage Storage >backup (or name of your app).
If you are able to see the name of your container there, it means the upload to iCloud has been completed successfully.
Conclusion
In the steps above, we first configured an app identifier, an iCloud container in our apple developer account, then we added our iCloud container to our app identifier and created a provisioning profile. Next, we added the iCloud capability to our xcode project and wrote the code to enable uploading our file to iCloud container. We also tracked the upload progress and verified that the file was infact stored on the iCloud container.
I’ll be adding a new article shortly that’ll enable us to download the data that we stored on the iCloud drive, so please subscribe and stay tuned.