Обновление текста метки несколько раз при нажатии кнопки в Swift - PullRequest
0 голосов
/ 12 января 2019

в моем быстром проекте у меня есть кнопка, и мне нужно выполнить много работ, когда я нажимаю кнопку (скажем, эти работы занимают около 40 секунд с момента нажатия кнопки). Поэтому в течение этого периода моя кнопка находится в «выбранном» состоянии. Я хочу изменить текст метки несколько раз (каждый после выполнения определенных функций), пока нажата эта кнопка. Итак, у меня есть что-то вроде этого:

@IBOutlet weak var myLabel: UILabel!
@IBAction func myButton(_ sender: UIButton) {
    //Some huge functions which take 10 seconds to run
    self.myLabel.text = "Some text1"

    //Some other huge functions which take 10 seconds to run
    self.myLabel.text = "Some text2"

    //Some other other huge functions which take 10 seconds to run
    self.myLabel.text = "Some text3"

    //Some other other other huge functions which take 10 seconds to run
    self.myLabel.text = "Some text4"
}

Но когда я нажимаю кнопку, все эти функции начинают работать и заканчивают работу, но я вижу только, что текст myLabel меняется на «Some text4», он никогда не изменится на «Some text1» или «Some text2» или «Some». text3 ", прежде чем стать" Some text4 ". Я подумал, что, возможно, установка DispatchQueue.main.async {} поможет, но все равно не работает. Любая идея? Благодарю.

Ответы [ 3 ]

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

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

func doSomething1() {
    // as good a way as any to simulate a long-running process
    sleep(1)
    DispatchQueue.main.async {
        self.myLabel.text = "Some text1"
    }
    DispatchQueue.global(qos: .background).async {
        self.doSomething2()
    }
}
func doSomething2() {
    sleep(1)
    DispatchQueue.main.async {
        self.myLabel.text = "Some text2"
    }
    DispatchQueue.global(qos: .background).async {
        self.doSomething3()
    }
}
func doSomething3() {
    sleep(1)
    DispatchQueue.main.async {
        self.myLabel.text = "Some text3"
    }
    DispatchQueue.global(qos: .background).async {
        self.doSomething4()
    }
}
func doSomething4() {
    sleep(1)
    DispatchQueue.main.async {
        self.myLabel.text = "Some text4"
    }
}

@IBAction func cmdDoStuff(_ sender: UIButton) {

    DispatchQueue.global(qos: .background).async {
        self.doSomething1()
    }
}
0 голосов
/ 12 января 2019

Поскольку ваш код является синхронным, код в строке выполняется сразу после кода в предыдущей строке. Таким образом, вы всегда будете видеть только последний установленный текст "Some text4"

Для вызова некоторого кода после того, как что-то сделано, мы используем обработчики завершения в Swift

func call(_ completion: @escaping (String)->Void) {
    completion("SomeText")
}

завершение вызова изнутри метода в тот момент, когда вам нужно, скажем, задание выполнено. Затем выполняется код внутри параметра завершения

call { text in // calling method
    self.myLabel.text = text // this is called after you call completion(:) from inside `call(:)`
}

Итак, давайте попробуем это с этой демонстрацией

@IBAction func myButton(_ sender: UIButton) {

    callAfter(2, text: "Text1") { text in
        print(text)
    }

    callAfter(4, text: "Text2") { text in
        print(text)
    }

    callAfter(6, text: "Text3") { text in
        print(text)
    }

}

func callAfter(_ duration: Double, text: String, _ completion: @escaping (String)->Void) {
    DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
        completion(text)
    }
}

... вы должны увидеть напечатанные Text1, Text2, Text3 в периоды 2, 4, 6 секунд с момента нажатия кнопки

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

Добавить блок завершения к вашей функции. Затем измените текст метки внутри блока завершения

typealias completionBlock = () -> Void

@IBOutlet weak var myLabel: UILabel!
@IBAction func myButton(_ sender: UIButton) {

    firstFunction {
        self.myLabel.text = "Some text1"
    }

    secondFunction {
        self.myLabel.text = "Some text2"
    }

    thirdFuntion {
        self.myLabel.text = "Some text3"
    }
}

func firstFunction(_ completion: @escaping completionBlock) {
    // your function body
    completion()
}

func secondFunction(_ completion: @escaping completionBlock) {
    // your function body
    completion()
}

func thirdFuntion(_ completion: @escaping completionBlock) {
    // your function body
    completion()

}
...