理解Swift中具有依赖性的操作序列
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解Swift中具有依赖性的操作序列相关的知识,希望对你有一定的参考价值。
引用https://developer.apple.com/reference/foundation/operation,我将游乐场设置为 -
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 finished")
}
op2.completionBlock = {
print("op2 finished")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
opsQue.addOperation(op1)
opsQue.addOperation(op2)
和控制台日志是 -
op1 working....
op2 working....
op1 finished
op2 finished
我们不应该期望输出是依赖的结果吗? -
op1 working....
op1 finished
op2 working....
op2 finished
使用相同的结果 - opsQue.addOperations([op1, op2], waitUntilFinished: true)
op1 working....
op2 working....
op1 finished
op2 finished
事实上,我无法确定为什么你的代码不能正常工作的神秘之处,但我想出了3个解决方法来实现你想要的:
如果您希望输出始终为:
op1 working....
op1 finished
op2 working....
op2 finished
然后:
1-您可能希望将第二个操作添加到第一个操作的完成块中的队列中,如下所示:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let opsQue = OperationQueue()
let op1 = myOperation1()
op1.completionBlock = {
print("op1 finished")
opsQue.addOperation(op2)
}
let op2 = myOperation2()
op2.completionBlock = {
print("op2 finished")
}
opsQue.addOperation(op1)
2-将maxConcurrentOperationCount操作队列设置为1,如下所示:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 finished")
}
op2.completionBlock = {
print("op2 finished")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
// setting maxConcurrentOperationCount to 1
opsQue.maxConcurrentOperationCount = 1
opsQue.addOperation(op1)
opsQue.addOperation(op2)
3-将第一个操作添加到队列后调用waitUntilAllOperationsAreFinished(),如下所示:
let opsQue = OperationQueue()
opsQue.addOperation(op1)
opsQue.waitUntilAllOperationsAreFinished()
opsQue.addOperation(op2)
顺便说一下,对于非复杂的任务,我更喜欢使用GCD。
希望这有帮助。
根据完成块的文件(强调我的),
您的完成块的确切执行上下文无法保证,但通常是辅助线程。因此,您不应该使用此块来执行任何需要非常特定的执行上下文的工作。 https://developer.apple.com/documentation/foundation/operation/1408085-completionblock
所以,从更真实的意义上说,当你想知道某个操作何时完成时,你会做更多这样的事情:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
//Do things
print("op1 finished")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
//Do things
print("op2 finished")
}
}
在依赖操作开始后调用完成块,但这并不意味着第一个操作没有结束。
正如在@ Xoronis的回答中引用的那样:
您的完成块的确切执行上下文无法保证,但通常是辅助线程。因此,您不应该使用此块来执行任何需要非常特定的执行上下文的工作。
https://developer.apple.com/documentation/foundation/operation/1408085-completionblock
看看这个例子:
class myOperation1 : Operation {
override func main() {
print("op1 working....")
for i in 1...10 {
print("(i)")
}
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 completed")
}
op2.completionBlock = {
print("op2 completed")
}
op2.addDependency(op1)
let opsQue = OperationQueue()
opsQue.addOperations([op1, op2], waitUntilFinished: true)
会导致
op1 working....
1
2
3
4
5
6
7
8
9
10
op2 working....
op1 completed
op2 completed
第一个操作在启动其依赖项之前结束,但在依赖项已经启动之后调用完成块。
您需要将maxConcurrentOperationCount设置为操作队列中的1,然后它将按预期工作。
let operationQueue = OperationQueue()
operationqueue?.maxConcurrentOperationCount = 1
let operation1 = Operation()
let operation2 = Operation()
operation1.completionBlock = {
print("operation1 finished")
}
operation2.completionBlock = {
print("operation2 finished")
}
operation2.addDependency(operation1)
operationQueue.addOperation(operation1)
operationQueue.addOperation(operation2)
通过指定依赖关系,可以保证op2
在op1
完成后被调度,但不一定op2
在op1
的完成处理程序完成后被调度。
初始化operationQueue暂停将给你你想要的。
let queue = OperationQueue()
let downloadOp = Operation()
let resizeOp = Operation()
downloadOp.dependency(resizeOp)
queue.isSuspended = true
queue.addOperation(downloadOp)
queue.addOperation(resizeOp)
queue.isSuspended = false
我测试使用isSuspended。每个操作完成后可以操作主队列。
class OperationChain: Operation {
var mainQ: OperationQueue?
var text: String?
init(with name: String, by mainqueue:OperationQueue){
self.text = name
self.mainQ = mainqueue
}
override func main() {
self.mainQ!.isSuspended = true
print(text!)
sleep(5)
self.mainQ!.isSuspended = false
}
}
let oq = OperationQueue()
oq.maxConcurrentOperationCount = 1
let q1 = OperationChain(with: "Operation.main.q1", by: oq)
print("q1")
q1.completionBlock = {
//sleep(5)
q1.mainQ!.isSuspended = true
var i = 0
repeat {
i = i + 1
} while i < 100
print("q1.completionBlock")
q1.mainQ!.isSuspended = false
}
oq.addOperations([q1], waitUntilFinished: true)
您可以使用适配器来确保执行的顺序:
op1 working....
op1 finished
op2 working....
op2 finished
这是修改后的代码:
import Foundation
class myOperation1 : Operation {
override func main() {
print("op1 working....")
}
}
class myOperation2 : Operation {
override func main() {
print("op2 working....")
}
}
let op1 = myOperation1()
let op2 = myOperation2()
op1.completionBlock = {
print("op1 finished")
}
op2.completionBlock = {
print("op2 finished")
}
let adapter = BlockOperation(block: {})
adapter.addDependency(op1)
op2.addDependency(adapter)
let opsQue = OperationQueue()
opsQue.addOperation(op1)
opsQue.addOperation(op2)
opsQue.addOperation(adapter)
以上是关于理解Swift中具有依赖性的操作序列的主要内容,如果未能解决你的问题,请参考以下文章