Can I receive count of records corresponding to CKQuery from CloudKit?
Aggregation queries are not possible in CloudKit. So you have to query all records and count those. To make sure that all records will be returned, you have to set operation.resultsLimit to a value larger than the count otherwise it could happen that not all records are returned.
CloudKit, NSPredicate to return a count or determine if any records exists , in a private container?
There is no way to get a count.
If you wish to determine if there are any records for a given record type, perform a CKQueryOperation
for the given record type. Set the query's predicate to [NSPredicate predicateWithValue:YES]
and set the operation's resultLimit
to 1
.
Then check the results. You'll either get one row back if there are any records or you'll get no rows back (or possible an error, see what happens).
Get the number of records that match a CloudKit query
There are no aggregation functions in CloudKit. The only way to do a count is by fetching all records.
CloudKit returns too many records
I just found out, that there is a bug in CloudKit, that deleted records are somehow hidden still available. I resetted my development environment and imported the data again and I got the correct amount of records returned.
More information can be found in this Stackoverflow post:
Deleted CloudKit records Reappear
Swift CloudKit and CKQuery: how to iteratively retrieve records when queryResultBlock returns a query cursor
No need for queryResultBlock
in Swift 5.5.
I use this because my CKRecord
types are always named the same as their Swift counterparts. You can replace recordType: "\(Record.self)"
with your recordType
if you want, instead.
public extension CKDatabase {
/// Request `CKRecord`s that correspond to a Swift type.
///
/// - Parameters:
/// - recordType: Its name has to be the same in your code, and in CloudKit.
/// - predicate: for the `CKQuery`
func records<Record>(
type _: Record.Type,
zoneID: CKRecordZone.ID? = nil,
predicate: NSPredicate = .init(value: true)
) async throws -> [CKRecord] {
try await withThrowingTaskGroup(of: [CKRecord].self) { group in
func process(
_ records: (
matchResults: [(CKRecord.ID, Result<CKRecord, Error>)],
queryCursor: CKQueryOperation.Cursor?
)
) async throws {
group.addTask {
try records.matchResults.map { try $1.get() }
}
if let cursor = records.queryCursor {
try await process(self.records(continuingMatchFrom: cursor))
}
}
try await process(
records(
matching: .init(
recordType: "\(Record.self)",
predicate: predicate
),
inZoneWith: zoneID
)
)
return try await group.reduce(into: [], +=)
}
}
}
Related Topics
How to Add Firebase to Today Extension iOS
How to Default Uilabel Font and Size Using Swift
Open Uiimagepickercontroller in Landscape Mode
Deprecated Warnings in Xcode and How to Handle Deprecation
Page Based "Reloadrootcontrollerswithnames:" on Launch Loop
Disable Autorotate on a Single Subview in iOS8
Handing Firebase + Facebook Login Process
How to Get All Nsrange of a Particular Character in a Nsstring
Urlsessiondelegate Function Not Being Called
How to Create a Uiimage with Uibezierpath
How to Detect "Clear" Notifications
Uiview Drawrect: Draw the Inverted Pixels, Make a Hole, a Window, Negative Space
How to Sign Out of Apple After Being Authenticated
Animating Calayer's Shadowpath Property
Download PDF and Save to the "Files" in Iphone, Not to the App Data, Swift