新的Cloud Kit框架广泛使用NSOperation进行CRUD。这些操作的结果以块为单位返回。例如:
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。你可以在fetchOperation1的completionBlock中嵌入fetchOperation2的init,但是你放弃了NSOperation的依赖功能,我试图在这里使用它。
所以,我正在寻找一个干净,可读,标准(没有反应性可可等)的解决方案,让NSOperation依赖项在其链中传递数据。
答案 0 :(得分:6)
我记得第一次介绍NSOperation
时,我必须为ADC网站写一篇介绍性文章,首先下载一些照片,然后将它们渲染成海报。我在那里遇到了类似的问题:使用依赖关系控制顺序,但后来发现我必须将图像文件名传递给依赖操作。
那是多年前的事了,当时我为每项任务都有NSOperation
个子类。我在它们之间设置了依赖关系,并为需要从早期操作传递结果的操作添加了委托。在委托方法中,控制器对象将从第一个操作的属性中检索结果,并通过第二个操作的属性设置它们。
或许更好的解决方案是使操作之间的关系显式化,不仅在依赖性方面,而且在数据传递方面。因此,您可以创建NSOperation
子类,将数据作为标准操作的一部分传递给下一个NSOperation
,或者 - 更优雅地 - 从已完成的操作中提取数据。
使这更具体:操作B取决于A是否完整。 A生成B运行所需的资源R.您向B添加一个引用A对象的属性。当B运行时,它只是从A对象中检索R.
如果您不想创建操作子类,并且只是想避免嵌套,您可以考虑使用排队机制来提供更多控制,例如CDEAsynchronousTaskQueue。
答案 1 :(得分:2)
只需在第一个块上方声明第二个操作,这样就可以设置要在其上获取的recordID,正如您对示例的编辑所示:
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设置为取消。因此,您不需要像自定义操作那样需要任何特殊的最终块。
答案 2 :(得分:1)
在这里,您可以找到4种不同的方法来在Swift中的两个操作之间传递数据。