Unbalanced call to dispatch_group_leave() on CloudKit CompletionBlock

873 views Asked by At

So I am building an iOS app working with CloudKit. A particular function calls for Products:

func getAllProducts(){

    //empty object in Singleton Class
    sharedStore.products.removeAllObjects()
    var products = NSMutableArray()

    //set up a query
    var predicate = NSPredicate(value: true)
    var query = CKQuery(recordType: "Product", predicate: predicate)

    //set in query operation
    var queryOperation = CKQueryOperation(query: query)

    //define method to catch fetched records
    //define completion block to process results
    queryOperation.queryCompletionBlock = { (cursor: CKQueryCursor!, error: NSError!) in
        if error != nil {
            //there was an error, get this error to the delegate
            self.delegate?.cloudKitReturnedError(error)
        } else {
            //there was no error
            println("no error")
            //cursor is used to know if there is more data to be fetched, so check cursor
            if cursor != nil {
                //there is more data to fetch
                println("more data to be fetched")
                //start new query
                let newOperation = CKQueryOperation(cursor: cursor)
                newOperation.completionBlock = queryOperation.completionBlock
                newOperation.recordFetchedBlock = queryOperation.recordFetchedBlock
                self.privateDB.addOperation(newOperation)
                dispatch_async(dispatch_group_enter(<#group: dispatch_group_t#>), <#block: dispatch_block_t##() -> Void#>)
            } else {
                println("all data fetched")
                self.delegate?.cloudKitReturnedArray!(products, identifier: "StoreProducts")
            }
        }
    }

    queryOperation.recordFetchedBlock = { (record: CKRecord!) in
        let product = self.saveProduct(record)

        if product.categoryReference == nil {
            products.addObject(product)
        }
    }

    //add the operation
    self.privateDB .addOperation(queryOperation)
}

Please note that all CloudKit communication happens in a dedicated CloudKitController class.

When large stacks of data are to be fetched, it does not load them at once but 'activates' it's cursor. However, when it does so, it apparently calls dispatch_group_leave() somewhere in background. When it's cursor starts receiving data, and it completes, my queryCompletionBlock is supposed to send a "finished" message to it's delegate, but instead I get this:

libdispatch.dylib`dispatch_group_leave:
0x1088edfd9 <+0>:  movl   $0x1, %eax
0x1088edfde <+5>:  lock   
0x1088edfdf <+6>:  xaddq  %rax, 0x40(%rdi)
0x1088edfe4 <+11>: incq   %rax
0x1088edfe7 <+14>: js     0x1088edffe               ; <+37>
0x1088edfe9 <+16>: movabsq $0x7fffffffffffffff, %rcx
0x1088edff3 <+26>: cmpq   %rcx, %rax
0x1088edff6 <+29>: jne    0x1088edffd               ; <+36>
0x1088edff8 <+31>: jmp    0x1088ee00e               ; _dispatch_group_wake
0x1088edffd <+36>: retq   
0x1088edffe <+37>: leaq   0x180c8(%rip), %rcx       ; "BUG IN CLIENT OF LIBDISPATCH: Unbalanced call to dispatch_group_leave()"
0x1088ee005 <+44>: movq   %rcx, 0x301a4(%rip)       ; gCRAnnotations + 8

-> 0x1088ee00c <+51>: ud2

I suppose I should call dispatch_group_enter() somehow in my code, but this whole asynchronous thing is new to me. I have read through Apple's documentation but I cannot manage to write a piece of code that does the job.

The question How do I prevent getting this Unbalanced call to "dispatch_group_leave()" when CloudKit works with a cursor to retrieve large stacks of data?

Any comments are highly appreciated.

0

There are 0 answers