Inside a performQuery
an other performQuery
is being called. The recordType
arguments are same for both, but the predicate
s are different.
The second performQuery
never returns, the App just runs and waits for CloudKit to respond.
The pseudo code is like this:
publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate), inZoneWithID: nil, completionHandler: {records, error in
if error == nil {
//.. problem is not name collision or reusing the same parameter, coming codepart is called though other methods
publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate2), inZoneWithID: nil, completionHandler: {records, error in
//THIS LINE WILL NEVER GET REACHED
if error == nil {
} else {
println(error.localizedDescription)
}
dispatch_semaphore_signal(sema2)
})
dispatch_semaphore_wait(sema2, DISPATCH_TIME_FOREVER)
//..
} else {
println(error.localizedDescription)
}
dispatch_semaphore_signal(sema)
})
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)
It looks like a semaphore threading issue. You are reusing the sama parameter. The last dispatch_semaphore_signal must be moved to above inside the else. Then the first dispatch_semaphore_wait can be removed completely. So it will be like this:
publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate), inZoneWithID: nil, completionHandler: {records, error in
if error == nil {
//.. problem is not name collision, it is nested though other blocks
publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate2), inZoneWithID: nil, completionHandler: {records, error in
//THIS LINE WILL NEVER GET REACHED
if error == nil {
} else {
println(error.localizedDescription)
}
dispatch_semaphore_signal(sema)
})
//..
} else {
println(error.localizedDescription)
dispatch_semaphore_signal(sema)
}
})
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)
Deadlock was fixed like this: Inner query moved after outer query. Both semaphore retained. Outer completion handler is finished before inner completion handler would start. From CloudKit returned records are stored in local variables.
var records: [AnyObject]! = []
publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate), inZoneWithID: nil, completionHandler: {records2, error in
if error == nil {
records = records2
} else {
println(error.localizedDescription)
}
dispatch_semaphore_signal(sema)
})
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER)
//HERE I can use records
var records3: [AnyObject]! = []
publicDatabase.performQuery(CKQuery(recordType: recordTypeSrc, predicate: predicate2), inZoneWithID: nil, completionHandler: {records4, error in
if error == nil {
records3 = records4
} else {
println(error.localizedDescription)
}
dispatch_semaphore_signal(sema2)
})
dispatch_semaphore_wait(sema2, DISPATCH_TIME_FOREVER)
//HERE I can use records3 too
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.