Как заставить цикл ждать, пока задача не будет завершена

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

let names = ["peter", "susan", "john", "peter", "susan", "john"]
var holding = [String: [Double]]()


for i in 0...10 {

    for name in names {

        if holding[name] == nil {
            Alamofire.request("https://jsonplaceholder.typicode.com", parameters: parameters).responseJSON { responseData in

                    // do stuff here
                    holding[name] = result
            }

        } else {
            // do other stuff with existing "holding[name]"

        }

        // if if holding[name] == nil, the whole process should wait
    }
}

Если я использую DispatchGroup, запросы Alamofire выполняются один за другим, но весь цикл не распознает, существует ли уже holding[name]. Таким образом, holding[name] всегда равно nil, потому что цикл не ждет.

Большое спасибо!

РЕДАКТИРОВАТЬ:

Согласно ответам Майка и Версуса, я пробовал следующее:

var names = ["peter", "susan", "john", "peter", "susan", "john"]
var holding = [String: [Double]]()

let semaphore = DispatchSemaphore(value: 1)

for i in 0...10 {

    DispatchQueue.global().async { [unowned self] in
        self.semaphore.wait()

        for name in names {

            if holding[name] != nil {
                Alamofire.request("https://jsonplaceholder.typicode.com", parameters: parameters).responseJSON { responseData in

                    // do stuff here
                    holding[name] = result
                    semaphore.signal()
                }

            } else {
                // do other stuff with existing "holding[name]"
                semaphore.signal()

            }

            // if if holding[name] != nil, the wholeprocess should wait
        }
    }
}

Но, к сожалению, приложение вылетает. Что я делаю не так?


person Josch Hazard    schedule 07.09.2017    source источник
comment
Связан ли этот вопрос с вашим проблема?   -  person Ahmad F    schedule 07.09.2017
comment
Где происходит сбой приложения и что такое журнал?   -  person Prashant Tukadiya    schedule 07.09.2017
comment
Это проще всего: картинка   -  person Josch Hazard    schedule 07.09.2017
comment
Удалите unowned и повторите попытку.   -  person Prashant Tukadiya    schedule 07.09.2017


Ответы (2)


У вас есть два варианта здесь

1 ) Semaphore

2 ) Operation Queues

Но вы должны дважды подумать, прежде чем идти с Semaphores

вам нужно быть осторожным с парой semaphore.signal() и semaphore.wait()

Поскольку Semaphore может блокировать главный поток, все операции должны выполняться в Dispatch.global.async

т.е.

semaphore.wait()

Alamofire.request("https://jsonplaceholder.typicode.com", parameters: parameters).responseJSON { responseData in

                     semaphore.signal()
                    holding[name] = result

 }

Здесь вы блокируете основной поток

Проблема в том, что обработчик завершения выполняется в основном потоке, который уже был заблокирован вызовом semaphore.wait() изначально. Поэтому, когда происходит завершение, semaphore.signal() никогда не вызывается

Вы должны пойти с

 DispatchQueue.global().async { [unowned self] in
        self.semaphore.wait()
        // And other statemetns 

    }

Надеюсь, это будет полезно вам и другим

person Prashant Tukadiya    schedule 07.09.2017
comment
Спасибо, это похоже на правильный путь. Я сделал я попробовать с вами предложение. Но приложение вылетает. Что я делаю не так? Смотрите обновление. - person Josch Hazard; 07.09.2017

Я думаю, вы можете использовать DispatchSemaphore, чтобы остановить цикл:

let semaphore = DispatchSemaphore(value: 1)
for i in 0...10 {

    for name in names {
        // if signal is 0, loop will be stopped forever,  
        // if signal > 0, loop will continue 
        semaphore.wait()
        if holding[name] == nil {
        Alamofire.request("https://jsonplaceholder.typicode.com", parameters: parameters).responseJSON { responseData in

                // do stuff here
                // release signal to continue current loop(signal + 1)
                semaphore.signal()
                holding[name] = result
            }

        } else {
        // do other stuff with existing "holding[name]"

        }

    // if if holding[name] == nil, the whole process should wait
    }
}
person Versus    schedule 07.09.2017
comment
Я только что попробовал. К сожалению, это не заставляет цикл ждать. - person Josch Hazard; 07.09.2017