2014-06-25 40 views
11

新的Cloud Kit框架對其CRUD使用了廣泛的NSOperation。這些操作的結果以塊形式返回。例如:如何在NSOperation依賴關係之間交流結果?

let fetchOperation = CKFetchRecordsOperation(recordIDs: [recordID1, recordId2]) 

fetchOperation.fetchRecordsCompletionBlock = {(dict: NSDictionary!, error: NSError!) -> Void in 
      // dict contains RecordId -> Record    
      // do something with the records here (if no error) 
     } 

欲鏈幾個這些操作(依賴關係)的,並通過一個操作的結果在鏈中的下一個操作。簡化的例子來說明這個(僞代碼!):

let fetchOperation1 = CKFetchRecordsOperation(recordIDs: [recordID1, recordId2]) 

fetchOperation1.fetchRecordsCompletionBlock = {(dict: NSDictionary!, error: NSError!) -> Void in 
      if error { 
       // handle error 
      } else { 
       // dict contains RecordId -> Record    
       // let's pretend our records contain references to other records 
       // that we want to fetch as well 
       fetchOperation.operationResult = 
        dict.allValues().map(
         { $0.getObject("referencedRecordId"} 
       ) 
      } 
     } 

let fetchOperation2 = CKFetchRecordsOperation(recordIDs: fetchOperation1.operationResult) 

fetchOperation2.fetchRecordsCompletionBlock = {(dict: NSDictionary!, error: NSError!) -> Void in 
      if error { 
       // handle error 
      } else { 
       // dosomething 
      } 
     } 

fetchOperation2.addDependency(fetchOperation2) 

但上述僞代碼不能工作,因爲當你初始化fetchOperation2的fetchOperation1.operationResult尚未分配。你可以將fetchOperation2的init嵌套在fetchOperation1的completionBlock中,但是你會拋棄NSOperation的依賴性功能,我試圖在這裏使用它。

因此,我正在尋找一個乾淨可讀的標準(無反應可可等)解決方案,讓NSOperation依賴關係在其鏈條中傳遞數據。

+0

如果您在創建第一個操作的完成一塊的第二操作,第二操作將永遠是第一位之後運行。爲什麼不管你是否分配依賴關係,如果你仍然可以按順序執行? –

+0

@TomHarrington這是一個簡化的例子。我有一個操作A將結果發送到操作B1和操作B2,它們需要將它們的結果發送到操作C.嵌套變得非常快速(又名'callback hell'),並且需要一個模式來使'complex '這樣的情況。 –

回答

6

我記得當NSOperation第一次被介紹時,我不得不爲ADC網站撰寫一篇介紹性文章,首先下載一些照片,然後將它們呈現爲海報。我遇到過類似的問題:使用依賴來控制順序,但後來發現我必須將圖像文件名傳遞給依賴操作。

那是多年前,當時我有NSOperation每個任務的子類。我在它們之間設置了依賴關係,並且將一個委託添加到了需要傳遞來自早期操作結果的操作。在委託方法中,控制器對象將從第一個操作的屬性中檢索結果,並通過第二個屬性設置它們。

也許更好的解決方案是將操作之間的關係顯式化,不僅在依賴性方面,而且在數據傳遞方面。因此,您可以創建NSOperation子類,將數據作爲標準操作的一部分傳遞給下一個NSOperation,或者更優雅地—從完成的操作中提取數據。

爲了使這更具體:操作B取決於A是完整的。 A生成B運行所需的資源R.您將一個屬性添加到引用A對象的B中。當B運行時,它只是從A對象中檢索R.

如果您不想創建操作子類,並且只是想避免嵌套塊,您可以考慮使用排隊機制,使您有更多的控制權,如CDEAsynchronousTaskQueue

+0

WWDC 2015高級NSOperations對此有很多提供。 – Andy

+0

不幸的是它沒有。在此共享數據的唯一示例是使用臨時高速緩存文件在網絡操作和解析操作之間共享數據。這就像隱藏的全球單身人士 – Mindaugas

2

剛剛宣佈第二操作的第一塊上面,所以你可以設置recordIDs給它取,與此編輯您的例子證明:

let fetchOperation1 = CKFetchRecordsOperation(recordIDs: [recordID1, recordId2]) 
let fetchOperation2 = CKFetchRecordsOperation() 

fetchOperation1.fetchRecordsCompletionBlock = {(dict: NSDictionary!, error: NSError!) -> Void in 
      if error { 
       // handle error 
      } else { 
       // dict contains RecordId -> Record    
       // let's pretend our records contain references to other records 
       // that we want to fetch as well 
       fetchOperation2.recordIDs = 
        dict.allValues().map(
         { $0.getObject("referencedRecordId"} 
       ) 
      } 
     } 

fetchOperation2.fetchRecordsCompletionBlock = {(dict: NSDictionary!, error: NSError!) -> Void in 
      if error { 
       // handle error 
      } else { 
       // dosomething 
      } 
     } 

fetchOperation2.addDependency(fetchOperation1) 

此外,如果你在你的第一個塊得到一個錯誤,你應該取消隊列上的所有操作。每個塊仍然會被調用,但它會將NSError設置爲取消。因此,您不需要像定製操作那樣使用任何特殊的最終塊。