2014-10-10 31 views
1

performQuery裏面另一個performQuery被調用。兩個參數的recordType參數相同,但predicate不同。兩個CloudKit可以相互調用死鎖嗎?怎麼修?

第二個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) 

回答

0

死鎖是這樣修復的:內查詢在外查詢後移動。兩個信號都保留下來。外部完成處理程序在內部完成處理程序啓動之前完成。從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 
0

它看起來像一個信號線程問題。您正在重新使用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) 
+0

我用兩個不同的信號 – 2014-10-10 09:25:57

+0

啊,好吧,你不需要2信號燈的,你可以使用我上面提到的結構。它不應該是一個接一個執行多個查詢的問題。我以前做過。也許嘗試執行沒有信號量的代碼?那麼至少你應該看到一些日誌記錄(如果你有這個) – 2014-10-10 09:28:08

+0

我不能留下信號量,外層查詢需要內層查詢返回值,看起來儘管它只是一個讀操作,CloudKit鎖表直到關閉結束 – 2014-10-10 10:06:38