Запустите другой фоновый процесс после завершения первого автоматически - PullRequest
0 голосов
/ 14 января 2019

У меня есть этот метод

func reminderInitialSetup() {
         DispatchQueue.global(qos: .background).async {

        let center = UNUserNotificationCenter.current()
        center.removeAllPendingNotificationRequests() 

        for i in (0..<self.arrayMyGoals.count) {

            let tempDict1 = self.arrayMyGoals[i] as! NSMutableDictionary;

            var goal_days : String!

            guard let days = tempDict1.value(forKey: "goal_dates") as? String else{
                return
            }
            goal_days = days

            let goal_time = tempDict1.value(forKey: "goal_time") as! String;

            let goal_name = tempDict1.value(forKey: "goal_name") as! String;

            let goalId : Int!

            goalId = tempDict1.object(forKey: "goal_id") as? Int                
            if goal_days.count > 0 {

                var datesArray = [Any]()

                datesArray = goal_days.components(separatedBy: ",")

                for  j in (0..<datesArray.count){

                    self.setReminder(date: datesArray[j] as! String, time: goal_time, title: goal_name, goalId: String(goalId))

                }
            }


        }
        DispatchQueue.main.async {

        }
    }

}

Этот метод вызывается, когда я получаю ответ от веб-службы на нажатие кнопки в фоновом режиме. Когда я снова нажимаю кнопку, случается, что метод выполняется в фоновом режиме, и изменяется число объектов в массиве MyMoals, что приводит к сбою. Я хочу запустить другой фоновый процесс автоматически после завершения предыдущего

Как мне этого добиться

Ответы [ 2 ]

0 голосов
/ 14 января 2019

Для этого вы можете использовать очереди операций. Пример:

let operationQueue: OperationQueue = {
    let operationQueue = OperationQueue()
    operationQueue.qualityOfService = .background
    operationQueue.maxConcurrentOperationCount = 1
    return operationQueue
}()

func runTask(id: String) {
    // optional: cancel all previous operations if about to start a new one
    // operationQueue.cancelAllOperations()
    operationQueue.addOperation {
        var wait = 0
        for _ in 0 ..< 10000 {
            wait += 1
        }
        DispatchQueue.main.async {
            print("task \(id) finished")
        }
    }
}

runTask(id: "t1")
runTask(id: "t2")
runTask(id: "t3")

Выход:

task t1 finished
task t2 finished
task t3 finished
0 голосов
/ 14 января 2019

Я бы создал последовательную очередь, и при каждом нажатии кнопки я увеличивал счетчик в процессе (например, func incrementRequestCount ()) в этой последовательной очереди, чтобы указать, сколько запросов необходимо сделать.

Затем я бы запустил процесс (например, func invokeWebRequestIfNeeded ()) в этой последовательной очереди, который проверяет значение счетчика, а если оно больше 0, уменьшает его и вызывает ваш метод для выполнения веб-запроса.

Когда я получаю ответ из Интернета, я выполняю любую необходимую обработку (в последовательной очереди), а затем снова вызываю invokeWebRequestIfNeeded ().

Если пользователь нажал кнопку, когда это происходило, то счетчик будет один или несколько, поэтому invokeWebRequestIfNeeded () снова вызовет ваш метод.

В конце концов количество требуемых запросов упадет до нуля, и invokeWebRequestIfNeeded () завершится без действий.

Может быть, есть более быстрые способы сделать это ... но когда меня бросают, мне нравятся вещи простые и очевидные.

...