Как достичь функциональности DispatchGroup с помощью OperationQueue? [Дубликат]

Эта альтернатива полезна для инициализации статических переменных:

DateTimeFormatter myFormatter = new DateTimeFormatterBuilder()
                               .parseCaseInsensitive()
                               .appendPattern("dd-MMM-yyyy")
                               .toFormatter(Locale.ENGLISH);
6
задан WanderingScouse 27 February 2017 в 22:07
поделиться

4 ответа

Вы можете использовать операционные зависимости для инициирования некоторой операции после завершения ряда других операций:

let operationQueue = OperationQueue()

let completionOperation = BlockOperation {
    // do something
}

for object in objects {
    let operation = ...
    completionOperation.addDependency(operation)
    operationQueue.addOperation(operation)
}

OperationQueue.main.addOperation(completionOperation)
11
ответ дан Rob 15 August 2018 в 23:36
поделиться
  • 1
    Очень чистый. благодаря – WanderingScouse 28 February 2017 в 04:24
  • 2
    Эй, Роб, я сделал именно это, но мой completionOperation все еще досрочно уволен. Мои операции - это асинхронные сетевые операции, поэтому операция рассматривается только finished, когда ответ возвращается. Я прочитал, что мне нужно переопределить свойство isAsynchronous среди нескольких других, чтобы сделать его асинхронной операцией, но я прочитал, что свойство будет проигнорировано, если я добавлю операцию в очередь в любом случае. Поэтому я смущен тем, что делать. Не могли бы вы посоветовать далее? – Pavan 2 August 2017 в 12:24
  • 3
    «Я читал, что мне нужно переопределить свойство isAsynchronous среди нескольких других, чтобы сделать его асинхронной операцией», ... Да, если основная задача в операции асинхронна, то да, это правильно. См. stackoverflow.com/a/32322851/1271826 для реализации URLSession; см. stackoverflow.com/a/27022598/1271826 для реализации Alamofire. «Но я прочитал, что свойство будет проигнорировано, если я добавлю операцию в очередь в любом случае. & quot; ... Это, безусловно, неверно. Материал isAsynchronous имеет решающее значение при выполнении подкласса Operation для асинхронной задачи. – Rob 2 August 2017 в 13:19

Я использую следующее решение:

private let queue = OperationQueue()

private func addOperations(_ operations: [Operation], completionHandler: @escaping () -> ()) {
    DispatchQueue.global().async { [unowned self] in
        self.queue.addOperations(operations, waitUntilFinished: true)
        DispatchQueue.main.async(execute: completionHandler)
    }
}
0
ответ дан kasyanov-ms 15 August 2018 в 23:36
поделиться

Подходящим решением является KVO

. Прежде чем цикл добавит наблюдателя (предполагается, что queue является экземпляром OperationQueue)

queue.addObserver(self, forKeyPath:"operations", options:.new, context:nil)

Затем реализуем

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    if object as? OperationQueue == queue && keyPath == "operations" {
        if queue.operations.isEmpty {
            // Do something here when your queue has completed
            self.queue.removeObserver(self, forKeyPath:"operations")
        }
    } else {
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
    }
}

Изменить:

В Swift 4 намного проще

Объявить свойство:

var observation : NSKeyValueObservation?

и создать наблюдателя

observation = queue.observe(\.operationCount, options: [.new]) { [unowned self] (queue, change) in
    if change.newValue! == 0 {
        // Do something here when your queue has completed
        self.observation = nil
    }
}
2
ответ дан vadian 15 August 2018 в 23:36
поделиться
0
ответ дан dbolli 29 October 2018 в 06:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: