An iOS CloudKit Sharing Example

From Techotopia
Revision as of 04:30, 10 November 2016 by Neil (Talk | contribs) (Preparing the Project for CloudKit Sharing)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

PreviousTable of ContentsNext
An iOS 10 CloudKit ExampleAn Overview of iOS 10 Multitouch, Taps and Gestures


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book


The chapter entitled An Introduction to CloudKit Sharing provided an overview of the way in which CloudKit sharing works and the steps involved in integrating sharing into an iOS app. The intervening chapters have focused on the creation of a project that demonstrates the integration of CloudKit data storage into iOS apps, together with the use of CloudKit subscriptions to notify users of changes to stored data records. This chapter will extend the project created in the previous chapters to add CloudKit sharing to the CloudKitDemo app.


Contents


Preparing the Project for CloudKit Sharing

Launch Xcode and open the CloudKitDemo project created in the chapter entitled An iOS 10 CloudKit Example and subsequently updated in the An iOS 10 CloudKit Subscription Example chapter of this book. In you have not completed the tasks in the previous chapters and are only interested in learning about CloudKit sharing, a snapshot of the project is included as part of the sample code archive for this book at the following web page:

http://www.ebookfrenzy.com/web/ios10

Once the project has been loaded into Xcode, the CKSharingSupported key needs to be added to the project Info.plist file with a Boolean value of true. Select the Info.plist file in the Project Navigator panel so that it loads into the property editor. Add a new entry to the file with the key field set to CKSharingSupported, the type to Boolean and the value to YES as illustrated in Figure 51 1:


Adding the CKSharingSupported key to the Info.plist file

Figure 51-1

Adding the Share Button

The user interface for the app now needs to be modified to add a share button to the toolbar. Select the Main.storyboard file, locate the Bar Button Item in the Object Library panel and drag and drop an instance onto the toolbar so that it is position to the right of the existing Delete button. Once added, double-click on the button and change the text to read “Share”:


Adding the Share button to the CloudKit Sharing demo app

Figure 51-2


With the Share button still selected, display the Assistant Editor panel and establish an Action connection to a method named shareRecord.


Creating the CloudKit Share

The next step is to add some code to the shareRecord action method to initialize and display the UICloudSharingController and to create and save the CKShare object. Select the ViewController.swift file, locate the stub shareRecord method and modify it so that it reads as follows:

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

@IBAction func shareRecord(_ sender: AnyObject) {

    let controller = UICloudSharingController { controller, 
		preparationCompletionHandler in
        let share = CKShare(rootRecord: self.currentRecord!)

        share[CKShareTitleKey] = "An Amazing House" as CKRecordValue
        share.publicPermission = .readOnly

        let modifyRecordsOperation = CKModifyRecordsOperation(
			recordsToSave: [self.currentRecord!, share], 
			recordIDsToDelete: nil)

        modifyRecordsOperation.timeoutIntervalForRequest = 10
        modifyRecordsOperation.timeoutIntervalForResource = 10

        modifyRecordsOperation.modifyRecordsCompletionBlock = { 
			records, recordIDs, error in
            if error != nil {
                print(error?.localizedDescription)
            }
            preparationCompletionHandler(share, 
				CKContainer.default(), error)
        }
        self.privateDatabase?.add(modifyRecordsOperation)
    }

    controller.availablePermissions = [.allowPublic, .allowReadOnly]
    controller.popoverPresentationController?.barButtonItem = 
				sender as? UIBarButtonItem

    present(controller, animated: true)
} 

The code added to this method follows the steps outlined in the chapter entitled An Introduction to CloudKit Sharing to display the CloudKit sharing view controller, create a share object initialized with the currently selected record and save it to the user’s private database.

Accepting a CloudKit Share

Now that the user has the ability to create a CloudKit share, the app also needs to be modified to accept a share and display the shared record to the user. The first step in this process is to implement the userDidAcceptCloudKitShareWith method within the project app delegate class. Edit the AppDelegate.swift file and implement this method as follows:

func application(_ application: UIApplication, userDidAcceptCloudKitShareWith cloudKitShareMetadata: CKShareMetadata) {

    let acceptSharesOperation = 
	CKAcceptSharesOperation(shareMetadatas: [cloudKitShareMetadata])
    acceptSharesOperation.perShareCompletionBlock = { 
			metadata, share, error in
        if error != nil {
            print(error?.localizedDescription)
        } else {
            let viewController: ViewController =
                self.window?.rootViewController as! ViewController
            viewController.fetchShare(cloudKitShareMetadata)
        }
    }
    CKContainer(identifier: 
		cloudKitShareMetadata.containerIdentifier).add(
				acceptSharesOperation)
}

As outlined in the previous chapter, this delegate method creates a CKAcceptSharesOperation using the share metadata object passed in to the method. This operation is then performed on the CloudKit container referenced in the share metadata. The share operation has assigned to it a completion handler which, in this instance, is configured to call a method on the view controller named fetchShare. The next task is to implement this method.

Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book

Fetching the Shared Record

At this point the share has been accepted and a CKShareMetadata object provided from which information about the shared record may be extracted. All that remains before the app can be tested is to implement the fetchShare method within the ViewController.swift file:

func fetchShare(_ metadata: CKShareMetadata) {

    let operation = CKFetchRecordsOperation(
		recordIDs: [metadata.rootRecordID])

    operation.perRecordCompletionBlock = { record, _, error in


        if error != nil {
            print(error?.localizedDescription)
        }

        if record != nil {
            DispatchQueue.main.async() {
                self.currentRecord = record
                self.addressField.text =
                    record?.object(forKey: "address") as? String
                self.commentsField.text =
                    record?.object(forKey: "comment") as? String
                let photo =
                    record?.object(forKey: "photo") as! CKAsset
                let image = UIImage(contentsOfFile:
                    photo.fileURL.path)
                self.imageView.image = image
                self.photoURL = self.saveImageToFile(image!)
            }
        }
    }

    operation.fetchRecordsCompletionBlock = { _, error in
        if error != nil {
            print(error?.localizedDescription)
        }
    }

    CKContainer.default().sharedCloudDatabase.add(operation)
}

The method prepares a standard CloudKit fetch operation based on the record ID contained within the share metadata object and performs the fetch using the sharedCloudDatabase instance. On a successful fetch, the completion handler is used to extract the data from the shared record and display it to the user.

Testing the CloudKit Share Example

To fully test CloudKit sharing, two devices with different Apple IDs need to be used. If you have access to two devices, create a second Apple ID for testing purposes and sign in using that ID on one of the devices. Once logged in, make sure that the devices are able to send and receive iMessage messages between each other and install and run the CloudKitDemo on both devices. Once the testing environment is set up, launch the CloudKitDemo app on one of the devices and add a record to the private database. Once added, tap the Share button and use the share view controller interface to send a share link to the Apple ID associated with the second device. When the message arrives within the Messages app on the second device, tap the share link and accept the share when prompted to do so. Once the share has been accepted, the CloudKitDemo app should launch and display the shared record.

Summary

This chapter put the theory of CloudKit sharing outlined in the chapter entitled An Introduction to CloudKit Sharing into practice by enhancing the CloudKitDemo project to include the ability to share CloudKit-based records with other app users. This involved the creation and saving of a CKShare object, use of the UICloudSharingController class and the addition of code to handle the acceptance and fetching of a shared CloudKit database record.


Learn SwiftUI and take your iOS Development to the Next Level
SwiftUI Essentials – iOS 16 Edition book is now available in Print ($39.99) and eBook ($29.99) editions. Learn more...

Buy Print Preview Book



PreviousTable of ContentsNext
An iOS 10 CloudKit ExampleAn Overview of iOS 10 Multitouch, Taps and Gestures