在一个performQuery
内部,正在调用另一个performQuery
。两者的recordType
参数相同,但predicate
参数不同。
第二个performQuery
永远不会返回,应用程序只是运行并等待CloudKit响应。
伪代码如下:
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)
这看起来像是一个信号量线程问题。您正在重用sama参数。最后一个dispatch_semaphore_signal必须移动到else内部的上方。然后可以完全去除第一个dispatch_semaphore_wait。所以它将是这样的:
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)
死锁是这样修复的:内部查询在外部查询之后移动。两个信号灯都保留了。外部完成处理程序在内部完成处理程序启动之前完成。从CloudKit返回的记录存储在本地变量中。
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