1

My schema is as follows

RecordType: OwnedEvents contains an element called "Owner". This Owner element points to CKReference created from a RecordType of type "OwnedEvents".

I have N OwnedEvents objects all pointing to one Owner object.

When I execute a query to retrieve all the records that point a given Owner object, I see that, in some cases, the query does not return all the records that point to it (it does return it in most cases). It also does not return an error in the completion block. When I go to the CloudKit dashboard, I see that all OwnedEvents objects are pointing to the same and correct Owner object as expected. The code I am using to retrieve is below.

My questions are:

  1. Is this kind of "silent" failure expected? I.e Do I need to identify this and recover? OR Am I doing something wrong in my query?

  2. Is there any way to say the query must return an error if not all records matching the criterion are retrieved? (i.e an atomic version of fetch..I guess not, since it is tough to know ahead of time what the expected number of matching records is, but I am wondering if there is something I can specify in the fetch or in the schema that hints at min number of records expected in the fetch result).

  3. Is it more efficient to fetch using a predicate formed using a reference compared to fetch that uses a predicate of the form "Get all records of type OwnedEvents with Column X > N1 and Column X

    • The reference is pointed to be same set of records, N1...N2
    • I.e If the reference based retrieval is going to be unreliable I might as well go away from it and take a brute force approach, if it is not any faster. At least in latter I have a easy way of identifying errors

Code used

CKReference* recordToMatch = [[CKReference alloc] initWithRecordID:eventCollectionID                                                
action:CKReferenceActionDeleteSelf]; //eventCollectionID is recordID of Record of type Owner

NSPredicate* predicate = [NSPredicate predicateWithFormat:@"Owner == %@", recordToMatch];


// Create the query object.
CKQuery* query = [[CKQuery alloc] initWithRecordType:@"OwnedEvents" predicate:predicate];

CKQueryOperation *queryObject = [[CKQueryOperation alloc] initWithQuery:query] ;


queryObject.queryCompletionBlock = ^(CKQueryCursor * cursor, NSError * operationError) {

    if(operationError)
    {
        DDLogError(@"Error %@ occured during query",operationError) ;
    }
    else if(cursor)
    {
        DDLogVerbose(@"Not all objects satisfying the query were returned.  Need to get next batch") ;
        //To do fetch remaining entries
        CKQueryOperation *queryObject = [[CKQueryOperation alloc] initWithCursor:cursor] ;
        //Execute another query with this object
    }
    else
    {
        DDLogVerbose(@"All objects satisfying the query were returned") ;
        //Take appropriate action with rcvd data
    }
} ;


queryObject.recordFetchedBlock = ^(CKRecord *record) {
    DDLogVerbose(@"Received record with seq Num: %@, type",record[@"SequenceNumber"],record[@"EventType"]) ;
    //Check if items are in sequence
} ;


[self.publicDatabase addOperation:queryObject] ;
Smart Home
  • 801
  • 7
  • 26
  • 1
    In cases where you don't seem to get all expected results, is the `cursor` parameter of the completion block set? The code you posted doesn't properly use the cursor if it's set. – rmaddy Mar 25 '16 at 20:36
  • Thanks, rmaddy. I see the issue even in cases where there was no cursor returned. In some cases I see the following: The Owner is pointed to by N ownedEvents records. First two records will come, 3rd record will not come (even though it is there in the DB) and then rest of records will come. After reading your comment, I changed my code to name the CKQueryOperation variable initialized using the cursor to newQueryObject (instead of queryObject), but I am still seeing issues. Was there any other issue in how I am using the cursor? – Smart Home Mar 28 '16 at 16:59

0 Answers0