正在取消操作队列 Swift
Canceling OperationQueue Swift
我在学习OperationQueue
。我想做的是在有通话时阻止网络通话。问题是当我点击按钮时,一个新的操作被添加到队列中。
class ViewController: UIViewController {
private var queue = OperationQueue()
func networkCall(completion: (()->Void)?) {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3)) {
completion?()
}
}
lazy var button: UIButton = {
let b = UIButton(type: .custom)
b.backgroundColor = .black
b.setTitleColor(.white, for: .normal)
b.setTitle("CLICK!~", for: .normal)
b.addTarget(self, action: #selector(self.boom), for: .touchUpInside)
return b
}()
@objc func boom() {
print("BOOM!")
self.queue.maxConcurrentOperationCount = 1
let block = BlockOperation()
block.addExecutionBlock {
self.networkCall {
print("DONE NETWORK CALL!")
}
}
self.queue.addOperation(block)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
self.queue.cancelAllOperations()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .gray
self.view.addSubview(self.button)
self.button.translatesAutoresizingMaskIntoConstraints = false
self.button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
self.button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
self.button.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
self.button.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
}
}
我是不是漏掉了什么?
不幸的是,您不能只向 BlockOperation
添加异步方法。提交异步网络请求后,操作本身将立即完成(即使您已将 completion?()
任意延迟 3 秒)。
相反,您需要将网络请求包装在自定义的异步 Operation
子类方法中,该方法执行所有 KVO 通知以实现正确的 Operation
行为。有关详细信息,请参阅 Operation
documentation。
请参阅 for example with downloadTask
implementation. Or see 进行一般性讨论。
顺便说一下,即使您不会使用 BlockOperation
,在您使用的情况下,请注意 BlockOperation
的 addExecutionBlock
。例如,您可以有一个串行队列,创建一个 BlockOperation
,然后为给定操作添加多个 addExecutionBlock
,并且它们 不会 是串行的。单个操作将连续运行,但不是您添加到给定 BlockOperation
的单个块。我通常建议人们避免使用 addExecutionBlock
和 BlockOperation
,直到你真正理解那里发生了什么。最好在初始化 BlockOperation
.
时只使用主闭包
我在学习OperationQueue
。我想做的是在有通话时阻止网络通话。问题是当我点击按钮时,一个新的操作被添加到队列中。
class ViewController: UIViewController {
private var queue = OperationQueue()
func networkCall(completion: (()->Void)?) {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(3)) {
completion?()
}
}
lazy var button: UIButton = {
let b = UIButton(type: .custom)
b.backgroundColor = .black
b.setTitleColor(.white, for: .normal)
b.setTitle("CLICK!~", for: .normal)
b.addTarget(self, action: #selector(self.boom), for: .touchUpInside)
return b
}()
@objc func boom() {
print("BOOM!")
self.queue.maxConcurrentOperationCount = 1
let block = BlockOperation()
block.addExecutionBlock {
self.networkCall {
print("DONE NETWORK CALL!")
}
}
self.queue.addOperation(block)
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(1)) {
self.queue.cancelAllOperations()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .gray
self.view.addSubview(self.button)
self.button.translatesAutoresizingMaskIntoConstraints = false
self.button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true
self.button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
self.button.widthAnchor.constraint(equalToConstant: 100.0).isActive = true
self.button.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
}
}
我是不是漏掉了什么?
不幸的是,您不能只向 BlockOperation
添加异步方法。提交异步网络请求后,操作本身将立即完成(即使您已将 completion?()
任意延迟 3 秒)。
相反,您需要将网络请求包装在自定义的异步 Operation
子类方法中,该方法执行所有 KVO 通知以实现正确的 Operation
行为。有关详细信息,请参阅 Operation
documentation。
请参阅 downloadTask
implementation. Or see
顺便说一下,即使您不会使用 BlockOperation
,在您使用的情况下,请注意 BlockOperation
的 addExecutionBlock
。例如,您可以有一个串行队列,创建一个 BlockOperation
,然后为给定操作添加多个 addExecutionBlock
,并且它们 不会 是串行的。单个操作将连续运行,但不是您添加到给定 BlockOperation
的单个块。我通常建议人们避免使用 addExecutionBlock
和 BlockOperation
,直到你真正理解那里发生了什么。最好在初始化 BlockOperation
.