Create a blinking label

I have a normal label and want that Label to blink three times, by changing the backgroundcolor from red to black an so on. I did some research and many people work with Timer or animations, but I cannot change this methods, like I need them. What can I do to make my Label blink?
Answered by OOPer in 656311022

I tired this in the viewDidLoad() function,

It would be better if you could show more context.

There's one very simple principle in iOS programming: NEVER call sleep.
(Never call blocking functions in the main thread.)

All the UI updates begins when the current task in the main thread is finished.
UI updates starts after viewDidLoad() is finished, meaning all the intermediate results are not shown and only the last result done in viewDidLoad() will be shown with very long delay.

As you wrote yourself, using Timer is one of the right ways:
Code Block
caption.backgroundColor = .black
var backgroundColorIsRed = false
var blinkCount = 0
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) {timer in
backgroundColorIsRed.toggle()
self.caption.backgroundColor = backgroundColorIsRed ? .systemRed : .black
blinkCount += 1
if blinkCount >= 4 {
timer.invalidate()
}
}




What can I do to make my Label blink?

Please show what you have tried till now. Even if it may not work as you expect, that would be very useful to write an answer.
I tired this in the viewDidLoad() function, but this does not show me the blinking, instead the View show up, when the for-loop has finished.
Code Block
caption.backgroundColor = UIColor.black
for _ in 0...2{
var bool = false
if bool{
caption.backgroundColor = UIColor.black
bool = false
}
else {
caption.backgroundColor = UIColor.systemRed
bool = true
}
sleep(1)
}



Accepted Answer

I tired this in the viewDidLoad() function,

It would be better if you could show more context.

There's one very simple principle in iOS programming: NEVER call sleep.
(Never call blocking functions in the main thread.)

All the UI updates begins when the current task in the main thread is finished.
UI updates starts after viewDidLoad() is finished, meaning all the intermediate results are not shown and only the last result done in viewDidLoad() will be shown with very long delay.

As you wrote yourself, using Timer is one of the right ways:
Code Block
caption.backgroundColor = .black
var backgroundColorIsRed = false
var blinkCount = 0
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) {timer in
backgroundColorIsRed.toggle()
self.caption.backgroundColor = backgroundColorIsRed ? .systemRed : .black
blinkCount += 1
if blinkCount >= 4 {
timer.invalidate()
}
}




I did this with a UIView extension

Code Block
extension UIView { 
func flashIt(repeated: Int, cycleTime: Double, delayed: Double = 5.0) {
if repeated < 0 { return }
let initAlpha = self.alpha
UIView.animate(withDuration: cycleTime, //Time duration
delay: delayed,
options:[.allowUserInteraction, .curveEaseInOut, .autoreverse, .repeat],
animations: {
UIView.setAnimationRepeatCount(Float(repeated)) // repeat 3 times.
self.alpha = 0.1 // Not 0.0, to allow user interaction
},
completion: { (done: Bool) in self.alpha = initAlpha } )
}
}


In your case, instead of setting the alpha, just set the background color.
And restore it in completion.
@OOPer thank you very much for you advice and the solution! It works like it should. Now I call a method in the viewDidLoad() called blinkred(), is that correct?

Now I call a method in the viewDidLoad() called blinkred(), is that correct?

It depends on how you implemented blinkred(), but I guess you have done it correctly if you can see the right result.
Create a blinking label
 
 
Q