what’s new in cloudkit€¦ · cloudkit js and web services wwdc 2015 what's new in cloudkit...
Post on 14-Jul-2020
23 Views
Preview:
TRANSCRIPT
© 2016 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.
There's a lot we want to share
App Frameworks #WWDC16
Session 226
What’s New in CloudKit
Paul Seligman CloudKit EngineerJacob Farkas CloudKit EngineerVanessa Hong CloudKit Engineer
What are we talking about?Table of Contents
What are we talking about?Table of Contents
CloudKit Overview
What are we talking about?Table of Contents
CloudKit OverviewTelemetry
What are we talking about?Table of Contents
CloudKit OverviewTelemetryAPI Improvements
What are we talking about?Table of Contents
CloudKit OverviewTelemetryAPI ImprovementsSharing
What is CloudKit?CloudKit Overview
Data everywhere!CloudKit Overview
Data everywhere!CloudKit Overview
iCloud Database
Data everywhere!CloudKit Overview
iCloud DatabaseExtensive use inside Apple
Data everywhere!CloudKit Overview
iCloud DatabaseExtensive use inside AppleUbiquitous
Prior talksCloudKit Overview
Introducing CloudKit WWDC 2014
Introducing CloudKit WWDC 2014
Advanced CloudKit WWDC 2014
CloudKit JS and Web Services WWDC 2015
What's New in CloudKit WWDC 2015
CloudKit Tips and Tricks WWDC 2015
Prior talksCloudKit Overview
Introducing CloudKit WWDC 2014
Advanced CloudKit WWDC 2014
CloudKit JS and Web Services WWDC 2015
What's New in CloudKit WWDC 2015
CloudKit Tips and Tricks WWDC 2015
https://developer.apple.com/cloudkit
Prior talksCloudKit Overview
Core objectsCloudKit Overview
ContainerDatabaseRecordRecord Zone
Core objectsCloudKit Overview
ContainerDatabaseRecordRecord Zone
Core objectsCloudKit Overview
ContainerDatabaseRecordRecord Zone
CloudKit Overview
ContainerDatabaseRecordRecord Zone
CloudKit Container
Core objects
CloudKit Overview
ContainerDatabaseRecordRecord Zone
CloudKit Container
Public Database Private Database
Core objects
CloudKit Overview
CloudKit Container
Public Database Private Database Shared Database
NEW
ContainerDatabaseRecordRecord Zone
Core objects
Core objectsCloudKit Overview
ContainerDatabaseRecordRecord Zone
Key ValueTitle String
Body String
CreationDate Date
Folder Reference
Note
Core objects
Record Zone
CloudKit Overview
ContainerDatabaseRecordRecord Zone
Database
Core objects
Record Zone
CloudKit Overview
ContainerDatabaseRecordRecord Zone
Database
Record
ContainerDatabaseRecordRecord Zone
RecordRecord
Database
CloudKit Overview
RecordRecordRecordRecordRecordRecordRecordRecord
Record Zone
RecordRecord
Core objects
Core objects
Database
CloudKit Overview
Default Zone Custom Zone
ContainerDatabaseRecordRecord Zone
RecordRecord
RecordRecord
Record Record
Record Record
RecordRecordRecordRecord
ContainerDatabaseRecordRecord Zone
Core objects
Private Database
CloudKit Overview
Public Database Shared Database
Default Zone Default Zone
Custom Zone
Custom Zone
Shared Zone
Shared Zone
Core objectsCloudKit Overview
ContainerDatabaseRecordRecord Zone
Core objectsCloudKit Overview
ContainerDatabaseRecordRecord ZoneShare
NEW
Core objects
Private Database
CloudKit Overview
ContainerDatabaseRecordRecord ZoneShare
NEW
Database
Custom Zone
RecordRecordRecord
RecordRecord
Record
RecordRecord
RecordRecord
Share
Share
Apple usage
CloudKit Container
CloudKit Overview
Public Database Shared DatabasePrivate Database
Apple usage
CloudKit Container
CloudKit Overview
Public Database Shared DatabasePrivate Database
Apple usage
CloudKit Container
CloudKit Overview
Public Database Shared DatabasePrivate Database
Apple usage
CloudKit Container
CloudKit Overview
Public Database Shared DatabasePrivate Database
CloudKit Is Now Available Everywhere
CloudKit Is Now Available Everywhere
CloudKit Is Now Available Everywhere
CloudKit Is Now Available Everywhere
CloudKit JS Web Services
CloudKit Is Now Available Everywhere NEW
CloudKit JS Web Services
macOS
macOS
No Mac App Store requirement
macOS
No Mac App Store requirement• Add iCloud Capabilities via your provisioning profile
Web
Server to server
Web
Server to server• Acts as admin user
Web
Server to server• Acts as admin user• Uses public/private key pair registered on CloudKit Dashboard
Web
Server to server• Acts as admin user• Uses public/private key pair registered on CloudKit Dashboard• Access to public database
watchOS 3
watchOS 3
Alternative to watch connectivity code
watchOS 3
Alternative to watch connectivity codeStandalone functionality
watchOS 3
Alternative to watch connectivity codeStandalone functionality• Can work without phone present (via wifi)
watchOS 3
Alternative to watch connectivity codeStandalone functionality• Can work without phone present (via wifi)
Full* CloudKit API
*offer does not include CKSubscription
watchOS 3
Alternative to watch connectivity codeStandalone functionality• Can work without phone present (via wifi)
Full* CloudKit APISimilar code on all Apple platforms
*offer does not include CKSubscription
watchOS 3
Alternative to watch connectivity codeStandalone functionality• Can work without phone present (via wifi)
Full* CloudKit APISimilar code on all Apple platformsLimited resources
*offer does not include CKSubscription
Visualize your app's behavior on the CloudKit DashboardTelemetry
Visualize your app's behavior on the CloudKit DashboardTelemetry
NEW
Visualize your app's behaviorTelemetry
CloudKit Dashboard
Visualize your app's behaviorTelemetry
CloudKit DashboardPublic DB
Visualize your app's behaviorTelemetry
CloudKit DashboardPublic DBAggregated Private DBs
Visualize your app's behaviorTelemetry
CloudKit DashboardPublic DBAggregated Private DBsHour/day/week/month
Visualize your app's behaviorTelemetry
CloudKit DashboardPublic DBAggregated Private DBsHour/day/week/monthPer Operation type/all Operations
Telemetry
Telemetry
Performance
Correctness
Correctness
Detect client changes with abnormally frequent errors
Correctness
Detect client changes with abnormally frequent errorsError handling is essential
API Improvements
API Improvements
NEW
API Improvements
Long Lived OperationsCKOperation TimeoutsHandling Many Record Zones Fetching Multiple Change Sets
API Improvements
Long Lived OperationsCKOperation TimeoutsHandling Many Record ZonesFetching Multiple Change Sets
Don’t repeat your workLong-Lived Operations
Don’t repeat your workLong-Lived Operations
Operations keep running if your application exits
Don’t repeat your workLong-Lived Operations
Operations keep running if your application exitsCallbacks saved by CloudKit
Don’t repeat your workLong-Lived Operations
Operations keep running if your application exitsCallbacks saved by CloudKitOperation can be replayed later
API Improvements
Long Lived OperationsCKOperation TimeoutsHandling Many Record ZonesFetching Multiple Change Sets
API Improvements
Long Lived OperationsCKOperation TimeoutsHandling Many Record Zones Fetching Multiple Change Sets
How long do you want to wait?CKOperation Timeouts
QualityOfService Behavior on broken network
userInteractive
userInitiated
utility
background
default
How long do you want to wait?CKOperation Timeouts
QualityOfService Behavior on broken network
userInteractive timeout after 60 seconds
userInitiated timeout after 60 seconds
utility
background
default
How long do you want to wait?CKOperation Timeouts
QualityOfService Behavior on broken network
userInteractive timeout after 60 seconds
userInitiated timeout after 60 seconds
utility timeout after 7 days
background timeout after 7 days
default timeout after 7 days
How long do you want to wait?CKOperation Timeouts
QualityOfService Behavior on broken network
userInteractive timeout after 60 seconds
userInitiated timeout after 60 seconds
utility timeout after 7 days
background timeout after 7 days
default timeout after 7 days
How long do you want to wait?CKOperation Timeouts
QualityOfService Behavior on broken network
userInteractive timeout after 60 seconds
userInitiated timeout after 60 seconds
utility timeout after 7 days
background timeout after 7 days
default timeout after 7 days
How long do you want to wait?CKOperation Timeouts
How long do you want to wait?CKOperation Timeouts
Network inactivity• Use the timeoutIntervalForRequest property on CKOperation• Default value is 60 seconds
How long do you want to wait?CKOperation Timeouts
Network inactivity• Use the timeoutIntervalForRequest property on CKOperation• Default value is 60 seconds
Start-to-finish timeout• Use the timeoutIntervalForResource property on CKOperation• Default value is 7 days• CKOperation may stay around longer
API Improvements
Long Lived OperationsCKOperation TimeoutsHandling Many Record Zones Fetching Multiple Change Sets
API Improvements
Long Lived OperationsCKOperation TimeoutsHandling Many Record ZonesFetching Multiple Change Sets
CKFetchRecordZonesOperation • Poll for all record zones in a database
Reduce payloads and roundtripsHandling Many Record Zones
CKFetchRecordZonesOperation • Poll for all record zones in a database
Reduce payloads and roundtripsHandling Many Record Zones
CKFetchRecordZonesOperation • Poll for all record zones in a database
Reduce payloads and roundtripsHandling Many Record Zones
CKFetchRecordZonesOperation • Poll for all record zones in a database
Reduce payloads and roundtripsHandling Many Record Zones
CKDatabaseSubscription• Receive a push for each change in a database
CKFetchDatabaseChangesOperation• Fetch ids of record zones with changes
CKFetchRecordChangesOperation • Track and fetch record changes on a
per-record-zone basis
Reduce payloads and roundtripsHandling Many Record Zones
CKDatabaseSubscription• Receive a push for each change in a database
CKFetchDatabaseChangesOperation• Fetch ids of record zones with changes
CKFetchRecordZonesOperation • Poll for all record zones in a database
CKFetchRecordChangesOperation • Track and fetch record changes on a
per-record-zone basis
Reduce payloads and roundtripsHandling Many Record Zones
CKDatabaseSubscription• Receive a push for each change in a database
CKFetchDatabaseChangesOperation• Fetch ids of record zones with changes
CKFetchRecordZonesOperation • Poll for all record zones in a database
Reduce payloads and roundtripsHandling Many Record Zones
CKDatabaseSubscription• Receive a push for each change in a database
CKFetchDatabaseChangesOperation• Fetch ids of record zones with changes
CKFetchRecordZonesOperation • Poll for all record zones in a database
CKFetchRecordChangesOperation • Track and fetch record changes on a
per-record-zone basis
Reduce payloads and roundtripsHandling Many Record Zones
CKFetchRecordZoneChangesOperation • Fetch record changes over multiple record
zones in a single operation
CKDatabaseSubscription• Receive a push for each change in a database
CKFetchDatabaseChangesOperation• Fetch ids of record zones with changes
CKFetchRecordZonesOperation • Poll for all record zones in a database
CKFetchRecordChangesOperation • Track and fetch record changes on a
per-record-zone basis
CKDatabaseSubscriptionHandling Many Record Zones
Record Zone
Record Zone
Record Zone
Record Zone
Record
Record
Record
Record
Database
CKDatabaseSubscriptionHandling Many Record Zones
Record Zone
Record Zone
Record Zone
Record Zone
Record
Record
Record
Record
Database
Record
Record
CKDatabaseSubscriptionHandling Many Record Zones
Record Zone
Record Zone
Record Zone
Record Zone
Push
Record
Record
Record
Record
Database
Record
Record
CKDatabaseSubscriptionHandling Many Record Zones
Record Zone
Record Zone
Record Zone
Record Zone
Push
Record
Record
Record
Record
Database
Record
Record
CKFetchDatabaseChangesOperationHandling Many Record Zones
Record Zone
Record Zone
Record Zone
Record Zone
Record
Record
Record
Record
Database
Record
Record
CKFetchDatabaseChangesOperationHandling Many Record Zones
Record Zone
Record Zone
Record Zone
Record Zone
Record
Record
Record
Record
Database
Record
Record
CKFetchRecordZoneChangesOperationHandling Many Record Zones
Database
Record Zone
Record Zone
Record Zone
Record Zone
Record
Record
Record
Record
Record
Record
CKFetchRecordZoneChangesOperationHandling Many Record Zones
Database
Record Zone
Record Zone
Record Zone
Record Zone
Record
Record
Record
Record
Record
Record
API Improvements
Long Lived OperationsCKOperation TimeoutsHandling Many Record ZonesFetching Multiple Change Sets
API Improvements
Long Lived OperationsCKOperation TimeoutsHandling Many Record ZonesFetching Multiple Change Sets
Fetch Multiple Change Sets
public class CKFetchRecordChangesOperation : CKDatabaseOperation {
public var moreComing: Bool { get }
}
Remember this?
Fetch Multiple Change Sets
public class CKFetchRecordChangesOperation : CKDatabaseOperation {
public var moreComing: Bool { get }
}
Remember this?
Client code responsible for fetching next batch
Fetch Multiple Change Sets
public class CKFetchRecordChangesOperation : CKDatabaseOperation {
public var moreComing: Bool { get }
}
Remember this?
Client code responsible for fetching next batchCloudKit idle
Fetch Multiple Change SetsUse this instead
public class CKFetchRecordZoneChangesOperation : CKDatabaseOperation {
public var fetchAllChanges: Bool
}
Fetch Multiple Change SetsUse this instead
public class CKFetchRecordZoneChangesOperation : CKDatabaseOperation {
public var fetchAllChanges: Bool
}
CloudKit keeps pipeline full
Fetch Multiple Change SetsUse this instead
public class CKFetchRecordZoneChangesOperation : CKDatabaseOperation {
public var fetchAllChanges: Bool
}
// fetchAllChanges is true by default
CloudKit keeps pipeline full
Fetch Multiple Change SetsNew callback
public class CKFetchRecordZoneChangesOperation : CKDatabaseOperation {
public var recordZoneChangeTokensUpdatedBlock: ((CKRecordZoneID, CKServerChangeToken?,
Data?) -> Void)?
}
Fetch Multiple Change SetsNew callback
public class CKFetchRecordZoneChangesOperation : CKDatabaseOperation {
public var recordZoneChangeTokensUpdatedBlock: ((CKRecordZoneID, CKServerChangeToken?,
Data?) -> Void)?
}
Earlier record changes are safe to commit
Fetch Multiple Change SetsNew callback
public class CKFetchRecordZoneChangesOperation : CKDatabaseOperation {
public var recordZoneChangeTokensUpdatedBlock: ((CKRecordZoneID, CKServerChangeToken?,
Data?) -> Void)?
}
Earlier record changes are safe to commitNew server change token can be used on a new CKFetchRecordZoneChangesOperation
API Improvements
Long Lived OperationsCKOperation TimeoutsHandling Many Record Zones Fetching Multiple Change Sets
You and I are going to share some recordsSharing UI
Jacob Farkas
Sharing Records
public class CKShare : CKRecord
Sharing Records
What is shared? public class CKShare : CKRecord
Sharing Records
What is shared?Who is it shared with?
public class CKShare : CKRecord
Shared databaseSharing Overview
CloudKit Container
Public Database Shared DatabasePrivate Database
What is shared?Sharing Records
Private Database
What is shared?Sharing Records
Note
Private Database
What is shared?
Note
Sharing Records
Private Database
What is shared?
Note
Sharing Records
Private Database
Share public class CKShare : CKRecord {
public init(rootRecord : CKRecord)
}
What is shared?
Note
Sharing Records
Private Database
Share
public class CKShare : CKRecord {
public init(rootRecord : CKRecord)
}
Note
What is shared?
Note
Sharing Records
Private Database
Share
public class CKShare : CKRecord {
public init(rootRecord : CKRecord)
}
public class CKRecord {
public var share: CKReference? { get }
}Note
Who is it shared with?
Note
Sharing Records
Private Database
Share
Note
Who is it shared with?Sharing Records
Share
Note
Private Database
Who is it shared with?Sharing Records
Share
Note
Private Database
user@icloud.com
Who is it shared with?Sharing Records
Share
Note
Private Database
Share
Note
Private Database
Who is it shared with?Sharing Records
Share
Note
Private Database
Who is it shared with?Sharing Records
Who is it shared with?Sharing Records
Share
Note
Private Database
Share
Note
Private Database
Sharing RecordsShare URLs
Share
Note
Private Database
Sharing Records
https://www.icloud.com/notes/000Y4qow0owP6NOxDzs4qgi8Q
Share URLs
Share
Note
Private Database
Sharing Records
Family Grocery list”icloud.com/notes
Share URLs
Sharing Records
Owner Other User
Share
Note
Private Database
Accepting a share
Sharing Records
Owner Other User
Share
Note
Private Database
Accepting a share
Sharing Records
Share
Note
Private Database
Owner Other User
Accepting a share
Share
Note
Shared Database
Sharing Records
Share
Note
Private Database
Owner Other User
Accepting a share
Share
Note
Private Database
Share
Note
Shared Database
Sharing Records
Owner Other User
Share
Note
Private Database
Share
Note
Shared Database
Sharing Records
Share
Note
Private Database
Owner Other User
DemoSystem Sharing UI
Where does it live?CloudKit Sharing UI NEW
CloudKit
Where does it live?CloudKit Sharing UI NEW
CKRecord
CKShare
CKModifyRecordsOperation
…
CloudKit
Where does it live?CloudKit Sharing UI NEW
CKRecord
CKShare
CKModifyRecordsOperation
…
CloudKit
NSSharingService
NSItemProvider
AppKit
UICloudSharingController
UIKit
UICloudSharingControlleriOS Sharing API
// Create a CloudKit share record
let share = CKShare(rootRecord: rootRecord)
share[CKShareTitleKey] = "Shopping List”
share[CKShareThumbnailImageDataKey] = shoppingListThumbnail
// Create a CloudKit share record
let share = CKShare(rootRecord: rootRecord)
share[CKShareTitleKey] = "Shopping List”
share[CKShareThumbnailImageDataKey] = shoppingListThumbnail
// Create a CloudKit share record
let share = CKShare(rootRecord: rootRecord)
share[CKShareTitleKey] = "Shopping List”
share[CKShareThumbnailImageDataKey] = shoppingListThumbnail
// Create a CloudKit share record
let share = CKShare(rootRecord: rootRecord)
share[CKShareTitleKey] = "Shopping List”
share[CKShareThumbnailImageDataKey] = shoppingListThumbnail
// Create a cloud sharing controller
let sharingController = UICloudSharingController(share: share) {
(controller: UICloudSharingController,
prepareCompletionHandler : (CKShare?, CKContainer?, NSError?) -> Void) in
// Create a cloud sharing controller
let sharingController = UICloudSharingController(share: share) {
(controller: UICloudSharingController,
prepareCompletionHandler : (CKShare?, CKContainer?, NSError?) -> Void) in
// Save the share
let sharingController = UICloudSharingController(share: share) {
(controller: UICloudSharingController,
prepareCompletionHandler : (CKShare?, CKContainer?, NSError?) -> Void) in
let modifyOp = CKModifyRecordsOperation(recordsToSave: [rootRecord, share],
recordIDsToDelete: nil)
modifyOp.modifyRecordsCompletionBlock = { (_, _, error) in
prepareCompletionHandler(share, ckContainer, error)
}
self.container.privateCloudDatabase.add(modifyOp)
}
// Save the share
let sharingController = UICloudSharingController(share: share) {
(controller: UICloudSharingController,
prepareCompletionHandler : (CKShare?, CKContainer?, NSError?) -> Void) in
let modifyOp = CKModifyRecordsOperation(recordsToSave: [rootRecord, share],
recordIDsToDelete: nil)
modifyOp.modifyRecordsCompletionBlock = { (_, _, error) in
prepareCompletionHandler(share, ckContainer, error)
}
self.container.privateCloudDatabase.add(modifyOp)
}
// Save the share
let sharingController = UICloudSharingController(share: share) {
(controller: UICloudSharingController,
prepareCompletionHandler : (CKShare?, CKContainer?, NSError?) -> Void) in
let modifyOp = CKModifyRecordsOperation(recordsToSave: [rootRecord, share],
recordIDsToDelete: nil)
modifyOp.modifyRecordsCompletionBlock = { (_, _, error) in
prepareCompletionHandler(share, ckContainer, error)
}
self.container.privateCloudDatabase.add(modifyOp)
}
// Set sharing options
sharingController.availablePermissions = [.publicOnly, .readWrite]
sharingController.popoverPresentationController?.sourceView = myShareButton
sharingController.delegate = self
self.present(sharingController, animated:true, completion:nil)
// Set sharing options
sharingController.availablePermissions = [.publicOnly, .readWrite]
sharingController.popoverPresentationController?.sourceView = myShareButton
sharingController.delegate = self
self.present(sharingController, animated:true, completion:nil)
// Set sharing options
sharingController.availablePermissions = [.publicOnly, .readWrite]
sharingController.popoverPresentationController?.sourceView = myShareButton
sharingController.delegate = self
self.present(sharingController, animated:true, completion:nil)
// Set sharing options
sharingController.availablePermissions = [.publicOnly, .readWrite]
sharingController.popoverPresentationController?.sourceView = myShareButton
sharingController.delegate = self
self.present(sharingController, animated:true, completion:nil)
// Set sharing options
sharingController.availablePermissions = [.publicOnly, .readWrite]
sharingController.popoverPresentationController?.sourceView = myShareButton
sharingController.delegate = self
self.present(sharingController, animated:true, completion:nil)
NSSharingServicemacOS Sharing API
// Save the share
let itemProvider = NSItemProvider()
itemProvider.registerCloudKitShare { (prepareCompletionHandler :
(CKShare?, CKContainer?, NSError?) -> Void) in
// Save the share and root record
}
let sharingService = NSSharingService(named: NSSharingServiceNameCloudSharing)!
sharingService.delegate = self
sharingService.perform(withItems: [itemProvider])
// Save the share
let itemProvider = NSItemProvider()
itemProvider.registerCloudKitShare { (prepareCompletionHandler :
(CKShare?, CKContainer?, NSError?) -> Void) in
// Save the share and root record
}
let sharingService = NSSharingService(named: NSSharingServiceNameCloudSharing)!
sharingService.delegate = self
sharingService.perform(withItems: [itemProvider])
// Save the share
let itemProvider = NSItemProvider()
itemProvider.registerCloudKitShare { (prepareCompletionHandler :
(CKShare?, CKContainer?, NSError?) -> Void) in
// Save the share and root record
}
let sharingService = NSSharingService(named: NSSharingServiceNameCloudSharing)!
sharingService.delegate = self
sharingService.perform(withItems: [itemProvider])
// Save the share
let itemProvider = NSItemProvider()
itemProvider.registerCloudKitShare { (prepareCompletionHandler :
(CKShare?, CKContainer?, NSError?) -> Void) in
// Save the share and root record
}
let sharingService = NSSharingService(named: NSSharingServiceNameCloudSharing)!
sharingService.delegate = self
sharingService.perform(withItems: [itemProvider])
// Save the share
let itemProvider = NSItemProvider()
itemProvider.registerCloudKitShare { (prepareCompletionHandler :
(CKShare?, CKContainer?, NSError?) -> Void) in
// Save the share and root record
}
let sharingService = NSSharingService(named: NSSharingServiceNameCloudSharing)!
sharingService.delegate = self
sharingService.perform(withItems: [itemProvider])
// Define sharing options
func options(for: NSSharingService, share: NSItemProvider)-> NSCloudKitSharingServiceOptions
{
return [.allowPublic, .allowReadWrite]
}
// Define sharing options
func options(for: NSSharingService, share: NSItemProvider)-> NSCloudKitSharingServiceOptions
{
return [.allowPublic, .allowReadWrite]
}
// User clicked a share
public class NSApplication {
public func application(application: NSApplication,
userAcceptedCloudKitShareWith: CKShareMetadata)
}
// User clicked a share
public class NSApplication {
public func application(application: NSApplication,
userAcceptedCloudKitShareWith: CKShareMetadata)
}
public class UIApplication {
public func application(application: UIApplication,
userAcceptedCloudKitShareWith: CKShareMetadata)
}
// Add an Info.plist key for CloudKit Sharing
<key>CKSharingSupported</key>
<true/>
Web Sharing UICloudKit JS
Sharing In Depth
Vanessa Hong
Deep diveCommon Use Cases
Sharing multiple recordsZones in shared databaseCKShare internalsSharing APIsSpecial notes
A Note is not a single recordSharing Multiple Records
Note
A Note consists of many recordsSharing Multiple Records
Note
Asset
Media
A Note consists of many recordsSharing Multiple Records
Note
Asset
Media Links
Data
A Note consists of many recordsSharing Multiple Records
Note
Asset
Media Links
Data
Info
Participant should only see a subsetSharing Multiple Records
Note
Asset
Media Links
Data
Info
Tell us what should be sharedSharing Multiple Records
Note
Asset
Media Links
Data
Info
Records have a new propertypublic var parent: CKReference
Parent references define the hierarchy for sharingSharing Multiple Records
Note
Asset
Media Links
Data
Info
Parent Field
Records have a new propertypublic var parent: CKReference
Descendants linked to root record via the parent fieldSharing Multiple Records
Note
Asset
Media Links
Data
Info
Parent Field
Records have a new propertypublic var parent: CKReference
Create Share using CKShare(rootRecord:)Sharing Multiple Records
Note
Asset
Media Links
Data
Info
Share
Parent Field
Records have a new propertypublic var parent: CKReference
Shared DB is only a View into the owner’s private DBSharing Multiple Records
Shared Database
Participant
Private Database
Owner
After accepting, Participant sees only records with parentSharing Multiple Records
Shared Database
ParticipantOwner
Private Database
After accepting, Participant sees only records with parentSharing Multiple Records
Shared Database
ParticipantOwner
Private Database
After accepting, Participant sees only records with parentSharing Multiple Records
Shared Database
ParticipantOwner
Private Database
readWrite Participant cannot add a dangling CKRecordSharing Multiple Records
Shared Database
Participant
Private Database
Owner
readWrite Participant cannot add a dangling CKRecordSharing Multiple Records
Shared Database
Participant
Private Database
Owner
NEW
readWrite Participant cannot add a dangling CKRecordSharing Multiple Records
Shared Database
Participant
Private Database
Owner
NEW
Error
readWrite Participant cannot add a dangling CKRecordSharing Multiple Records
Shared Database
Participant
Private Database
Owner
NEW
Error
NEW
readWrite Participant cannot add a dangling CKRecordSharing Multiple Records
Shared Database
Participant
Private Database
Owner
Error: No Parent
NEW
Error
NEW
readWrite Participant can add a new parented CKRecordSharing Multiple Records
Shared Database
Participant
Private Database
Owner
readWrite Participant can add a new parented CKRecordSharing Multiple Records
Shared Database
Participant
Private Database
Owner
NEWNEW
Two owners, two sharesZones in Shared Database
Shared Database
“ShoppingList” Share “Shopping
List” Share
Two owners, two shares, two zonesZones in Shared Database
Shared Database
“ShoppingList” Share “Shopping
List” Share
Record Zone Record Zone
Two owners, two shares, two zonesZones in Shared Database
Shared Database
“ShoppingList” Share “Shopping
List” Share
Record Zone Record Zone
public class CKRecordZoneID {
public var zoneName: String
public var ownerName: String
}
Two owners, two shares, two zonesZones in Shared Database
public class CKRecordZoneID {
public var zoneName: String
public var ownerName: String
}
Shared Database
“ShoppingList” Share “Shopping
List” Share
zoneName: “Notes” zoneName: “Notes”
Two owners, two shares, two zonesZones in Shared Database
public class CKRecordZoneID {
public var zoneName: String
public var ownerName: String
}
Shared Database
“ShoppingList” Share “Shopping
List” Share
zoneName: “Notes” zoneName: “Notes”
Two owners, two shares, two zonesZones in Shared Database
public class CKRecordZoneID {
public var zoneName: String
public var ownerName: String
}
Shared Database
“ShoppingList” Share “Shopping
List” Share
zoneName: “Notes” zoneName: “Notes”ownerName: “_abcxyz” ownerName: “_1234567”
Two owners, two shares, two zonesZones in Shared Database
public class CKRecordZoneID {
public var zoneName: String
public var ownerName: String
}
Shared Database
“ShoppingList” Share “Shopping
List” Share
zoneName: “Notes” zoneName: “Notes”ownerName: “_abcxyz” ownerName: “_1234567”
Two owners, three shares, three zonesZones in Shared Database
“ShoppingList” Share “Shopping
List” Share
zoneName: “Notes” zoneName: “Notes”ownerName: “_abcxyz” ownerName: “_1234567”
“Recipe” Share
zoneName: “OtherZone”ownerName: “_abcxyz”
Shared Database
Two owners, three shares, three zonesZones in Shared Database
“ShoppingList” Share “Shopping
List” Share
zoneName: “Notes” zoneName: “Notes”ownerName: “_abcxyz” ownerName: “_1234567”
“Recipe” Share
zoneName: “OtherZone”ownerName: “_abcxyz”
Shared Database
Two owners, four shares, three zonesZones in Shared Database
“ShoppingList” Share “Shopping
List” Share
zoneName: “Notes” zoneName: “Notes”ownerName: “_abcxyz” ownerName: “_1234567”
“Recipe” Share
zoneName: “OtherZone”ownerName: “_abcxyz” “Great
Hiking Trails”
Share
Shared Database
Two owners, four shares, three zonesZones in Shared Database
“ShoppingList” Share
zoneName: “Notes” zoneName: “Notes”ownerName: “_abcxyz” ownerName: “_1234567”
“Recipe” Share
zoneName: “OtherZone”ownerName: “_abcxyz”
Shared Database
“ShoppingList” Share
“Great Hiking Trails”
Share
Prerequisite—Owner has existing Record(s) to shareCKShare
“Shopping List”
Prerequisite—Owner has existing Record(s) to shareCKShare
“Shopping List”
What to Share
Prerequisite—Owner has existing Record(s) to shareCKShare
“Shopping List”
What to Share
Share
How to Share
Is a CKRecord containing access controls for shared dataCKShare
Every CKShare has additional properties beyond a basic CKRecord
Is a CKRecord containing access controls for shared dataCKShare
Every CKShare has additional properties beyond a basic CKRecord
public class CKShare : CKRecord {
public var participants: [CKShareParticipant]
}
Share
public class CKShareParticipantParticipantParticipantParticipantParticipant
Owner sets up the ShareCKShare Lifecycle—Invite-Only
Share
Owner sets up the ShareCKShare Lifecycle—Invite-Only
1. Create a Share
Share
Owner sets up the ShareCKShare Lifecycle—Invite-Only
1. Create a Share2. publicPermission=none
publicPermission: none
Share
Owner sets up the ShareCKShare Lifecycle—Invite-Only
Participant #1
acceptanceStatus: invited
permission: readWrite
Participant #2
acceptanceStatus: invited
permission: readOnly
1. Create a Share2. publicPermission=none3. Add Participant
1. acceptanceStatus=invited2. Owner determines each
participant’s permission
publicPermission: noneparticipants:
Share
Owner sets up the ShareCKShare Lifecycle—Invite-Only
Participant #1
acceptanceStatus: invited
permission: readWrite
Participant #2
acceptanceStatus: invited
permission: readOnly
1. Create a Share2. publicPermission=none3. Add Participant
1. acceptanceStatus=invited2. Owner determines each
participant’s permission
4. Save the Share
publicPermission: noneparticipants:
Share
Owner sets up the ShareCKShare Lifecycle—Invite-Only
Participant #1
acceptanceStatus: invited
permission: readWrite
Participant #2
acceptanceStatus: invited
permission: readOnly
1. Create a Share2. publicPermission=none3. Add Participant
1. acceptanceStatus=invited2. Owner determines each
participant’s permission
4. Save the Share5. Owner gets URL
publicPermission: none
“Shopping List”icloud.com/notes
url:
participants:
Participant joins the ShareCKShare Lifecycle—Invite-Only
Share
publicPermission: none
“Shopping List”icloud.com/notes
url:
participants:
Participant #1
acceptanceStatus: invited
permission: readWrite
Participant #2
acceptanceStatus: invited
permission: readOnly
Participant joins the ShareCKShare Lifecycle—Invite-Only
Share 1. Participants accept via URLacceptanceStatus=accepted
publicPermission: none
“Shopping List”icloud.com/notes
url:
participants:
Participant #1
acceptanceStatus: invited
permission: readWrite
Participant #2
acceptanceStatus: invited
permission: readOnly
Participant #1
acceptanceStatus: accepted
permission: readWrite
Participant #2
acceptanceStatus: accepted
permission: readOnly
Owner sets up the ShareCKShare Lifecycle—readOnly or readWrite
Share
Owner sets up the ShareCKShare Lifecycle—readOnly or readWrite
1. Create a Share
Share
Owner sets up the ShareCKShare Lifecycle—readOnly or readWrite
1. Create a Share2. publicPermission=readOnly
or readWritepublicPermission: readOnly or readWrite
Share
Owner sets up the ShareCKShare Lifecycle—readOnly or readWrite
1. Create a Share2. publicPermission=readOnly
or readWrite3. Save the SharepublicPermission: readOnly or readWrite
Share
Owner sets up the ShareCKShare Lifecycle—readOnly or readWrite
1. Create a Share2. publicPermission=readOnly
or readWrite3. Save the Share4. Owner gets URL
“Shopping List”icloud.com/notes
url:
publicPermission: readOnly or readWrite
Participant joins the ShareCKShare Lifecycle—readOnly or readWrite
Share
Participant #1
acceptanceStatus: accepted
1. Anyone can join via URL. acceptanceStatus=accepted, permission is the same as the publicPermission
“Shopping List”icloud.com/notes
url:
publicPermission: readOnly or readWriteparticipants:
Lifecycle—end the share for a participantCKShare
Private DB
Owner
Shared DB
ParticipantParticipant leaves the Share by deleting the Share from their Shared DB
Lifecycle—end the share for a participantCKShare
Private DB
Owner
Shared DB
ParticipantParticipant leaves the Share by deleting the Share from their Shared DB
Lifecycle—end the share for a participantCKShare
Private DB
Owner
Shared DB
ParticipantParticipant leaves the Share by deleting the Share from their Shared DB
Owner can always remove any Participant
Lifecycle—End the share for everyoneCKShare
“Shopping List” Share
Owner deletes the Share from his private DB
Lifecycle—End the share for everyoneCKShare
“Shopping List”
Owner deletes the Share from his private DB
CKUserIdentityCKShareParticipant
Participant public class CKShareParticipant {
public var userIdentity: CKUserIdentity
…
}
public class CKUserIdentity {
public var lookupInfo: CKUserIdentityLookupInfo
public var nameComponents: PersonNameComponents
}
CKUserIdentityCKShareParticipant
Participant public class CKShareParticipant {
public var userIdentity: CKUserIdentity
…
}
public class CKUserIdentity {
public var lookupInfo: CKUserIdentityLookupInfo
public var nameComponents: PersonNameComponents
}
CKUserIdentityCKShareParticipant
Participant public class CKShareParticipant {
public var userIdentity: CKUserIdentity
…
}
public class CKUserIdentity {
public var lookupInfo: CKUserIdentityLookupInfo
public var nameComponents: PersonNameComponents
}
CKUserIdentityCKShareParticipant
Participant public class CKShareParticipant {
public var userIdentity: CKUserIdentity
…
}
public class CKUserIdentity {
public var lookupInfo: CKUserIdentityLookupInfo
public var nameComponents: PersonNameComponents
}
Mapped to iCloud accountsCKShareParticipant
Mapped to iCloud accounts
Participant #3
userIdentity.lookupInfo: <email>
Participant #4
userIdentity.lookupInfo: <phone>
Participant #2
userIdentity.lookupInfo: <phone>
Participant #1
userIdentity.lookupInfo: <email>
CKShareParticipant
Mapped to iCloud accounts
Participant #3
userIdentity.lookupInfo: <email>
Participant #4
userIdentity.lookupInfo: <phone>
Participant #2
userIdentity.lookupInfo: <phone>
Participant #1
userIdentity.lookupInfo: <email>
CKShareParticipant
Mapped to iCloud accounts
Participant #3
userIdentity.lookupInfo: <email>
Participant #4
userIdentity.lookupInfo: <phone>
Participant #2
userIdentity.lookupInfo: <phone>
Participant #1
userIdentity.lookupInfo: <email>
CKShareParticipant
No iCloud account
Verification flow to prove email ownership
No iCloud account
Verification flow to prove phone ownership
If you want to create your own Custom UISharing APIs
On behalf of the owner• Setting up the Share
On behalf of the participant• Accept the Share
watchOS and tvOS• Shared records available, but no System UI
Adding participantsOwner Sets Up the Share
Adding participantsOwner Sets Up the Share
CKFetchShareParticipantsOperation• Can look up via
- Email- Phone- CloudKit User Record ID
Adding participantsOwner Sets Up the Share
CKFetchShareParticipantsOperation• Can look up via
- Email- Phone- CloudKit User Record ID
• Returns CKShareParticipants
Adding participantsOwner Sets Up the Share
CKFetchShareParticipantsOperation• Can look up via
- Email- Phone- CloudKit User Record ID
• Returns CKShareParticipants
Pass CKShareParticipants to addParticipant
Adding participantsOwner Sets Up the Share
CKFetchShareParticipantsOperation• Can look up via
- Email- Phone- CloudKit User Record ID
• Returns CKShareParticipants
Pass CKShareParticipants to addParticipantCall CKModifyRecordsOperation to save the share
Fetch Share Metadata, then Accept the ShareParticipant Accepts a Share
CKFetchShareMetadataOperation• Converting a URL to CKShareMetadataPass CKShareMetadata to CKAcceptSharesOperation
LimitationsParticipant Accepts a Share
No nameComponents, for privacy reasonspublic class CKUserIdentity {
public var nameComponents: PersonNameComponents // empty
}
Verification flow only available via System UI:CKErrorParticipantMayNeedVerification
shareParticipant.userIdentity.lookupInfo.hasiCloudAccount
Invitees on older platformsSharing
Owner can invite anybody• Invitee may not have installed the latest operating system• Invitee may not have an Apple product
1280 x 800
1280 x 800
1280 x 800
1280 x 800
1280 x 800
Get your container ready for SharingSharing
CKRecordTypeShare• Behaves like any other Record Type in CloudKit• Can create custom fields• Can run queries
To trigger its creation• Share a record in a custom zone in any private database in the development environment• Deploy schema to productionNow, users in production can create Shares
What’s new is now oldSummary
CloudKit is available on all platformsTelemetry available on CloudKit DashboardAPI ImprovementsNew Feature—Sharing• Sharing System UI• Sharing APIs, Objects, and Lifecycle• Configure your fallback URL!
More Information
https://developer.apple.com/wwdc16/226
Related Sessions
CloudKit Best Practices Pacific Heights Friday 9:00AM
Labs
CloudKit and iCloud Lab Frameworks Lab D Thursday 4:00PM
CloudKit and iCloud Lab Frameworks Lab B Friday 12:00PM
top related