Отмена операцииQueue Swift - PullRequest
       40

Отмена операцииQueue Swift

2 голосов
/ 17 апреля 2020

Я учусь 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
    }
}

Я что-то упустил?

1 Ответ

0 голосов
/ 17 апреля 2020

К сожалению, вы не можете просто добавить асинхронный метод к BlockOperation. Сама операция завершится, как только будет отправлен асинхронный сетевой запрос (даже если вы отложили completion?() на 3 секунды позже).

Вместо этого вы захотите обернуть сетевой запрос в специальный асинхронный метод подкласса Operation, который выполняет все уведомления KVO для правильного поведения Operation. Подробнее см. Документацию Operation .

См. { ссылка }, например, с реализацией downloadTask. Или см. { ссылка } для общего обсуждения.


Кстати, даже если вы не будете использовать BlockOperation, в тех случаях, когда вы это делаете, помните о addExecutionBlock из BlockOperation. Вы можете, например, иметь последовательную очередь, создать BlockOperation, а затем добавить несколько addExecutionBlock для данной операции, и они не будут последовательными. Отдельные операции будут вести себя последовательно, но не отдельные блоки, которые вы добавляете к данному BlockOperation. Как правило, я бы советовал людям избегать addExecutionBlock с BlockOperation, пока вы действительно не поняли, что там происходит. Лучше просто использовать главное закрытие при инициализации BlockOperation.

...