Создайте несколько методов DispatchQueue.main.asyncAfter одновременно в Swift 3

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

@IBAction func playButtonPressed(_ sender: Any) {
    var index = 0.0
    var i = 0
    var j = 0
    while i < sites.count {
        while j < sites[i].count {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0*index) {
                self.plot(day:i,site:j)
            }
            j += 1
            index += 1
        }
        j = 0
        i += 1
    }
}

func plot(day:Int,site:Int) {
    for letter in glossary {
        let siteToPlot = sites[day][site]
        if let location = letter[siteToPlot] {
            setUpMap(name: location.name!, lat: location.lat!, long: location.long!)
        }
    }
}

Как я это настроил, каждый элемент в цикле for будет иметь метод, вызываемый в DispatchQueue.main.asyncAfter, но каждый элемент будет отправлен через секунду. Сначала будет 0 секунд, затем 1, затем 2 и т. Д.

Однако не похоже, что аргументы функции plot сохраняются, так как при первом вызове функции plot значения дня и сайта равны 9 и 0, которые являются их значениями после завершения цикла.

1 ответ

Решение

Вы можете исправить это, создав локальные переменные:

@IBAction func playButtonPressed(_ sender: Any) {
    var index = 0.0
    var i = 0
    var j = 0
    while i < sites.count {
        while j < sites[i].count {
            let day = i
            let site = j
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0 * index) {
                self.plot(day: day, site: site)
            }
            j += 1
            index += 1
        }
        j = 0
        i += 1
    }
}

Или, как указал Мартин Р в Pass значение для закрытия? Вы можете "захватить" эти переменные:

@IBAction func playButtonPressed(_ sender: Any) {
    var index = 0.0
    var i = 0
    var j = 0
    while i < sites.count {
        while j < sites[i].count {
            DispatchQueue.main.asyncAfter(deadline: .now() + 1.0 * index) { [i, j] in
                self.plot(day: i, site: j)
            }
            j += 1
            index += 1
        }
        j = 0
        i += 1
    }
}

Или лично я бы, наверное, использовал for петли, чтобы очистить это немного:

@IBAction func playButtonPressed(_ sender: Any) {
    var delay = 0.0
    for i in 0 ..< sites.count {
        for j in 0 ..< sites[i].count {
            DispatchQueue.main.asyncAfter(deadline: .now() + delay) { [i, j] in
                self.plot(day: i, site: j)
            }
            delay += 1
        }
    }
}
Другие вопросы по тегам