Swift Combine extensions for reactive CloudKit record processing. Designed for simplicity.
CombineCloudKit exposes CloudKit operations as
Combine publishers. Publishers can be used to process values over
time, using Combine’s declarative API.
📦 Adding CombineCloudKit to Your Project
CombineCloudKit supports Swift Package Manager,
CocoaPods, and Carthage. You can use whichever
you prefer, but Swift Package Manager is most likely to be supported in the future.
Because Carthage assumes dependencies are provided as shared frameworks, but Swift Package Manager builds only libraries
or executables, we have to generate an .xcodeproj for Carthage to use.
⚠️ The generate-xcodeproj command has been deprecated. This solution may stop working in a future release of the Swift
Package Manager.
Combine allows you to chain value processing Publishers
for one or more Subscribers. Here, we perform a query on
our CKDatabase, then process the results
asynchronously. As each CKRecord is read from the
database, it is passed to the map
publisher which publishes the value of the record’s name field. Any errors in the chain so far can be handled in the
catch publisher, which passes CKRecordValue values
along to our sink subscriber where the
final values are processed.
import CloudKit
import Combine
import CombineCloudKit
func queryDueItems(database: CKDatabase, due: Date) {
let cancellable = database
.performQuery(ofType: "ToDoItem", where: NSPredicate(format: "due >= %@", due))
.map { record: CKRecord -> CKRecordValue in
// Map each ToDoItem to its Name
print("Received record: \(record)")
return record["Name"]
}.catch { error: Error in
// Handle any upstream error
print("Received error: \(error)")
}.sink { value: CKRecordValue in
// Process the Name of each ToDoItems
print("Received result: \(value)")
}
// ...
}
Queueing and Cancellation
Just creating a Publisher does not queue a CloudKit operation. An operation is queued only once a Subscriber
subscribes to the Publisher and indicates
Demand.
Note that the Cancellable subscriber from
sink will cancel the upstream publishers
when it is deinitialized. Take care to ensure that your subscribers live long enough to process values. If a
CombineCloudKit publisher is cancelled before it is finished emitting values, the underlying
CKOperation will be cancelled. This may be desirable
when performing a query and processing only the first few results. However, failing to wait for completion of a save,
delete, or modify operation may result in undesirable cancellation.
Note that because the atBackgroundPriority publishers are built on CKDatabase methods that do not provide means of
cancellation, they will not respond to requests for cancellation. If you need the publishers to respond to requests for
cooperative cancellation, please use the publishers that do not have atBackgroundPriority in their names. You can
still specify
QualityOfService.background
by passing in a
CKOperation.Configuration.
Sharing Publishers among Multiple Subscribers
If two or more Subscribers subscribe to the same CombineCloudKit Publisher, the operation will be queued twice.
This may be surprising if you’re new to Combine! Queueing the same database operation twice could be inefficient or
potentially harmful. If you need to subscribe to a Publisher twice, use the
share and
makeConnectable
operators. This will ensure the operation is queued only once.
I considered making the Publishers all conform to
ConnectablePublisher
by default, but that would require all callers to call
connect
explicitly or to use the
autoconnect
operator, even if they did not intend to share the Publisher.
⛅️ CombineCloudKit
Swift Combine extensions for reactive CloudKit record processing. Designed for simplicity.
CombineCloudKit exposes CloudKit operations as Combine publishers. Publishers can be used to process values over time, using Combine’s declarative API.
📦 Adding CombineCloudKit to Your Project
CombineCloudKit supports Swift Package Manager, CocoaPods, and Carthage. You can use whichever you prefer, but Swift Package Manager is most likely to be supported in the future.
Swift Package Manager
Add a dependency on CombineCloudKit to your
Package.swiftusing Xcode or the Swift Package Manager. Optionally, specify a version requirement.Then resolve the dependency:
To update to the latest CombineCloudKit version compatible with your version requirement:
CocoaPods
Add a dependency on CombineCloudKit to your
Podfile. Optionally, specify a version requirement.Then install the dependency:
To update to the latest CombineCloudKit version compatible with your version requirement:
Carthage
Add a dependency on CombineCloudKit to your
Cartfile. Optionally, specify a version requirement.Because Carthage assumes dependencies are provided as shared frameworks, but Swift Package Manager builds only libraries or executables, we have to generate an
.xcodeprojfor Carthage to use.To update to the latest CombineCloudKit version compatible with your version requirement:
🌤 Using CombineCloudKit in Your Project
Combine allows you to chain value processing Publishers for one or more Subscribers. Here, we perform a query on our
CKDatabase, then process the results asynchronously. As eachCKRecordis read from the database, it is passed to themappublisher which publishes the value of the record’s name field. Any errors in the chain so far can be handled in the catch publisher, which passesCKRecordValuevalues along to oursinksubscriber where the final values are processed.Queueing and Cancellation
Just creating a
Publisherdoes not queue a CloudKit operation. An operation is queued only once aSubscribersubscribes to thePublisherand indicatesDemand.Note that the
Cancellablesubscriber fromsinkwill cancel the upstream publishers when it is deinitialized. Take care to ensure that your subscribers live long enough to process values. If a CombineCloudKit publisher is cancelled before it is finished emitting values, the underlyingCKOperationwill be cancelled. This may be desirable when performing a query and processing only the first few results. However, failing to wait for completion of asave,delete, ormodifyoperation may result in undesirable cancellation.Note that because the
atBackgroundPrioritypublishers are built onCKDatabasemethods that do not provide means of cancellation, they will not respond to requests for cancellation. If you need the publishers to respond to requests for cooperative cancellation, please use the publishers that do not haveatBackgroundPriorityin their names. You can still specifyQualityOfService.backgroundby passing in aCKOperation.Configuration.Sharing Publishers among Multiple Subscribers
If two or more
Subscribers subscribe to the same CombineCloudKitPublisher, the operation will be queued twice. This may be surprising if you’re new to Combine! Queueing the same database operation twice could be inefficient or potentially harmful. If you need to subscribe to aPublishertwice, use theshareandmakeConnectableoperators. This will ensure the operation is queued only once.I considered making the
Publishers all conform toConnectablePublisherby default, but that would require all callers to callconnectexplicitly or to use theautoconnectoperator, even if they did not intend to share thePublisher.For more on this topic, please review:
📘 Documentation
💯% documented using Jazzy. Hosted by GitHub Pages.
❤️ Contributing
Contributions are welcome!
📚 Further Reading
To learn more about Combine and CloudKit, watch these videos from WWDC:
…or review Apple’s documentation:
If you’re looking for Swift concurrency extensions for CloudKit using
async,await, andAsyncSequence, take a look at AsyncCloudKit!📜 License
CombineCloudKit was created by Chris Araman. It is published under the MIT license.