
This video is only available to subscribers. Start a subscription today to get access to this and 484 other videos.
CloudKit Notes Manager Continued
Episode
#277
|
14 minutes
| published on
June 22, 2017
| Uses iOS-10.3, Xcode-8.3
Subscribers Only
We finish the CloudKitNotesManager by providing a generic save and delete methods that we can use for any CKRecordWrapper type. We also implement a custom notification when a note is saved so that we can update an interested view controllers to update their UI.
This episode is part of a series: Hello CloudKit.
1. Hello Cloud Kit - Part 1 10 min |
2. Hello Cloud Kit - Part 2 10 min |
3. CloudKit Querying 12 min |
4. CloudKit References 7 min |
5. Fetching and Saving References 15 min |
6. Working with Images 15 min |
7. Fetching Paged Images 8 min |
8. CKRecord Upload Progress 6 min |
9. Isolating CloudKit from your Controllers 16 min |
10. Extracting CKRecordWrapper 7 min |
11. CloudKit Notes Manager 11 min |
12. CloudKit Notes Manager Continued 14 min |
new folder
New Folder Function
func newFolder(name: String) -> Folder {
return CloudKitFolder(name: name)
}
Saving Records Generically
fun save<R: CKRecordWrapper>(record: R,
conversion: @escaping (T) -> R,
completion: @escaping OperationCompletionBlock<T>) {
let modifyOp = CKModifyRecordsOperation(recordsToSave: [record.record], recordIDsToDelete: nil)
modifyOp.modifyRecordsCompletionBlock = { savedRecords, deletedRecords, error in
if let e = error {
print("Error saving folder: \(e)")
completion(.error(e))
}
if let savedRecord = savedRecords?.first {
let result = R(record: savedRecord)
completion(.success(conversion(result)))
}
}
database.add(modifyOp)
}
We can use this to save a note like this:
func save(note: Note, completion: @escaping (Result<Note>) -> Void) {
guard let note = note as? CloudKitNote else { fatalError("must pass in a CloudKitNote") }
save(record: note, conversion: { $0 }) { result in
switch result {
case .success(let savedNote):
NotificationCenter.default.post(name: .NoteWasUpdated, object: savedNote)
completion(.success(savedNote))
case .error(let e):
completion(.error(e))
}
}
}
Here we post a notification when a note is saved so any view controllers that are displaying the note can update their cnotents with the new note that is returned by the server.
Deleting Records Generically
private func delete<R:CKRecordWrapper>(record: R, completion: @escaping OperationCompletionBlock<Bool>) {
let modifyOp = CKModifyRecordsOperation(recordsToSave: nil, recordIDsToDelete: [record.record.recordID])
modifyOp.modifyRecordsCompletionBlock = { saved, deletedIds, error in
if let e = error {
print("Error deleting record: \(e)")
completion(.error(e))
} else {
let deletedCount = deletedIds?.count ?? 0
completion(.success(deletedCount > 0))
}
}
database.add(modifyOp)
}
We can the change our delete(folder:)
method to use this:
func delete(folder: Folder, completion: @escaping (Result<Bool>) -> Void) {
guard let folder = folder as? CloudKitFolder else { fatalError("must pass in a CloudKitFolder") }
delete(record: folder, completion: completion)
}
Fetching Notes in a Folder
func fetchNotes(for folder: Folder, completion: @escaping (Result<[Note]>) -> Void) {
guard let folder = folder as? CloudKitFolder else { fatalError("must pass in a CloudKitFolder") }
let inFolderPredicate = NSPredicate(format: "folder == %@", CKReference(recordID: folder.record.recordID, action: .deleteSelf))
let sortDescriptors = [NSSortDescriptor(key: "modificationDate", ascending: false)]
query(predicate: inFolderPredicate,
sortDescriptors: sortDescriptors,
conversion: { (note: CloudKitNote) -> Note in note },
completion: completion)
}