Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

grandM

macrumors 68000
Original poster
Oct 14, 2013
1,539
304
I was looking at following code.

Code:
@IBAction func startButtonTapped(_ sender: UIButton) {
        stopwatch.start()
        while stopwatch.isRunning {
            print("Updating \(stopwatch.elapsedTime)")
            elapsedTimeLabel.text = "\(stopwatch.elapsedTime)"
        }
    }

It's obvious this while loop will cause the user interface to go unresponsive as it is on the main thread of a stopwatch app. What astonishes me though is the label is never updated once. Is this because I never quit the while loop, hence never exit the IBAction method and the GUI is only updated upon exiting the startButton method?

Once again my gratitude!
 
Yes. Your code has been invoked from the main runloop and the runloop continues to execute after your code has exited. In fact, the label will be updated at the beginning of the next runloop cycle. Not after your code.

http://stackoverflow.com/questions/26178602/order-of-operations-in-runloop-on-ios
To get a better understanding. Is a run loop the logic of steps executed on a thread in this case the main thread? Each iteration of steps being one run. These runs are in a kind of while loop on a different thread.

This would mean that at run 47 for instance I hit the start button. This causes the IBAction to go into the while loop. As the while loop stays true I never get to leave run 47. As labels only get drawn at the next run (being 48) the label is not updated.

If this is true it's not the not exiting of the IBAction being the problem per se. It's the run 47 never being exited.

Do I love macrumors :)
 
I don't know if I understand your remrk correctly.
Any application has exactly one main thread and a main run loop associated with that thread.
The main thread schedukes all GUI interaction.
All user events like touch are proceseed on the main thread.

You can update GUI objects like UIButtons on different threads, but the layout and drawing still happens,on the main thread. (I know this is not entirely true, but lets just say it is)

You can even create your own runloop objects and call "run" on them.
You can adf run loop sources like network sockets to them.
But the GUI is handled by the main thread and the main run loop.

If you block that runloop, nothing is happening.
If any IBAction method blocks the main thread and the run loop, you App will be killed by a watchdog.

Thr run loop is just a loop like the one you programmmed.
Your code above is part of that loop. While your code runs, nothing elsenis happening on the main thread.
This is why GCD and the dispatch family of functions were invented.

I hope this helps. Otherwise pleas ask more specific questions.
If you want a label to display a sequence of increasing numbers, look up timers that are executec at intervals.
Incidentally they are parz of the runloop ad well ;)

Please feel free to continue this thread if you want to.

(Typed on iPad. Ignore all spekking please)
 
  • Like
Reactions: grandM
I was looking at following code.

Code:
@IBAction func startButtonTapped(_ sender: UIButton) {
        stopwatch.start()
        while stopwatch.isRunning {
            print("Updating \(stopwatch.elapsedTime)")
            elapsedTimeLabel.text = "\(stopwatch.elapsedTime)"
        }
    }

It's obvious this while loop will cause the user interface to go unresponsive as it is on the main thread of a stopwatch app. What astonishes me though is the label is never updated once. Is this because I never quit the while loop, hence never exit the IBAction method and the GUI is only updated upon exiting the startButton method?

Once again my gratitude!
It doesn't look like you are updating the UI on the main thread. That would explain why you aren't seeing the text change.

Also, I wouldn't do what you did to imitate a stop watch. You should use an NSTimer that fires a method on an interval to show the time progression. None of that code should be within an IBAction. The IBAction should have be used to start/stop the timer.
 
  • Like
Reactions: grandM
Almost all Cocoa/UI activity takes place when the OS is running iOS framework code in the main UI run loop. If your code is running, this iOS framework code is not.

If you want the UI code to run, you have to exit your code (both your while-loop and your iBAction method) completely. Then the label will update.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.