Marty
Marty

Reputation: 131

How to update a NSTextField Value during an action?

I am running a lengthly task in an Action and I would like to have a display of where I am at. For that I created a Text Field and I tried it with setStringValue:

[textField setStingValue: [NSSting stringWithFormat:@"%ld",currentValue]]

The code works but unfortunately it is not updating the NSTextField after every iteration but rather when the whole Action is done.

What am I doing wrong?

Upvotes: 0

Views: 860

Answers (2)

Scott Allen
Scott Allen

Reputation: 1189

When you click on a UI component, and it enters the Action block, the code is running on the main thread, the same thread that is painting the UI. If you run a long running operation in that block, it isn't going to paint until you are done because it is busy doing whatever you have it doing - you have hijacked the paint thread.

As said elsewhere, you need to spawn another thread, and then have the new thread perform the long running operation, and occasionally send messages to have the UI be updated by the main thread.

As a next step, go read the Apple documentation on NSThread, specifically:

+ (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument

Be aware that threading is a non-trivial domain area, and be ready for some wierd behavior if you aren't careful.

Upvotes: 1

zneak
zneak

Reputation: 138211

This is because applications with the Cocoa framework use an event loop to perform operations, and events occur in a completely serial fashion.

An event is basically any kind of action that the framework designer could not predict or found convenient to have run in a delayed manner. Since you can't predict when clicks will be performed, they need to be considered events; and for efficiency reasons (since you don't want to repaint a component multiple times if you don't need to), the repaint actions are events too.

Your action runs in response to a user event (for instance, a click on a button is an event) and therefore blocks all other events waiting in the queue until it's complete. However, components are repainted in response to a different, framework-triggered event, and as such the text field must wait until your action completes to repaint itself. This is why you cannot visually change the value of a text field from inside an action.

In order to notify your user of the progress of your task, you'll need to run it on a different thread. There's a lot to say about threads, so you should probably read some about them. I'm also sure that there are plenty of examples of how to run a long action in a background thread and update the UI accordingly for Cocoa all over the Internet.

Upvotes: 2

Related Questions