在Swift中按下按钮时多次更新标签文本

时间:2019-01-12 09:06:39

标签: swift label

在我的快速项目中,我有一个按钮,当我按下按钮时,我需要完成许多工作(可以说,从按下按钮的那一刻起,这些工作大约需要40秒钟)。因此,在这段时间里,我的按钮处于“选定”状态。我想要的是在按下此按钮的同时多次更改标签的文本(每次在完成特定功能之后)。所以我有这样的东西:

// Note that EditorFor template would iterate the list item for you
@Html.EditorFor(m => m.Model.StockTransactionsDetails) 

但是,当我单击按钮时,所有这些功能开始运行并完成,但是我只看到myLabel的文本更改为“ Some text4”,它将永远不会更改为“ Some text1”或“ Some text2”或“ Some text3”,然后变为“ Some text4”。我认为也许 DispatchQueue.main.async {} 会有所帮助,但仍然行不通。任何想法?谢谢。

3 个答案:

答案 0 :(得分:2)

由于您的代码是同步的,因此该行中的代码在上一行中的代码之后立即执行。因此,您将始终看到最后设置的文本"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)
    }
}

...您应该能够在按下按钮后的第二,四,六秒钟内看到Text1Text2Text3的打印内容

答案 1 :(得分:0)

将完成块添加到您的函数中。然后在完成块内更改标签文本

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()

}

答案 2 :(得分:0)

您可以在后台队列中运行所有长时间运行的任务,并在主队列中更新标签。关键是仅在第一个函数完成时才调用下一个函数,否则它们将并行运行,并且可以同时更新。这是一个例子

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()
    }
}