I've got a problem in trying to change a UILabel.text. It doesn't seem to want to change when called normally, eg. menuLabel.text = @"example";
This is being called in a "- (void) function" and there is an animating indicator running when the UILabel is set to change. Since a few things are running, I thought I'd try to open a new thread and call the following function.
[NSThread detachNewThreadSelector:@selector(changeLabel:) toTarget:self withObject:@"Checking for New Specials"];
Creating a new thread seems to work fine and the UILabel text changes, however I read somewhere that Apple says it's a bad idea to create a new thread that is dedicated for the GUI. Plus, I'll need to call changeLabel function a few times, as the text will change a few times.
Therefore, my questions is, any ideas why it doesn't work in the same thread as everything else. I understand I haven't really provided much code, but I guess I'm after some descriptions and explanations on what could cause this issue, and when is the best time to create new threads.
Thanks everyone... Also, I'm fairly new to all this.
I've got a problem in trying to change a UILabel.text. It doesn't seem to want to change when called normally, eg. menuLabel.text = @"example";
This is being called in a "- (void) function" and there is an animating indicator running when the UILabel is set to change. Since a few things are running, I thought I'd try to open a new thread and call the following function.
[NSThread detachNewThreadSelector:@selector(changeLabel:) toTarget:self withObject:@"Checking for New Specials"];
Creating a new thread seems to work fine and the UILabel text changes, however I read somewhere that Apple says it's a bad idea to create a new thread that is dedicated for the GUI. Plus, I'll need to call changeLabel function a few times, as the text will change a few times.
Therefore, my questions is, any ideas why it doesn't work in the same thread as everything else. I understand I haven't really provided much code, but I guess I'm after some descriptions and explanations on what could cause this issue, and when is the best time to create new threads.
Thanks everyone... Also, I'm fairly new to all this.
Changing the UI outside of the main thread is bad, and may cause unexpected results, or even crashes. Do not do it. Period.
I bet the problem is that your code is in a loop, and doesn't return until it's done. Cocoa is written such that UI changes don't take place until your code returns and visits the main event loop. If you want UI updates during a long process, you need to write it to either do the work in chunks, returning between chunks, or move the processing code to a separate worker thread, and have the processing code ask the main thread to update the UI:
Code:
- (void) workerThreadMethod;
{
//create an autorelease pool
NSAutoreleasePool* tempPool = [[NSAutoreleasePool alloc] init];
NSString* labelText;
for (i = 0; i < 100000; i++)
{
//Do some work here.
if (i % 100 == 0)
{
labelText = [NSString stringWithFormat: @"At step %d", i];
//The call below runs on the worker thread, but asks the
//main thread to update the UI.
[self.label performSelectorOnMainThread: @selector(setText:)
withObject: labelText];
}
//drain autorelease pool
[tempPool drain];
}
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
Changing the UI outside of the main thread is bad, and may cause unexpected results, or even crashes. Do not do it. Period.
I bet the problem is that your code is in a loop, and doesn't return until it's done. Cocoa is written such that UI changes don't take place until your code returns and visits the main event loop. If you want UI updates during a long process, you need to write it to either do the work in chunks, returning between chunks, or move the processing code to a separate worker thread, and have the processing code ask the main thread to update the UI:
Code:
- (void) workerThreadMethod;
{
//create an autorelease pool
NSAutoreleasePool* tempPool = [[NSAutoreleasePool alloc] init];
NSString* labelText;
for (i = 0; i < 100000; i++)
{
//Do some work here.
if (i % 100 == 0)
{
labelText = [NSString stringWithFormat: @"At step %d", i];
//The call below runs on the worker thread, but asks the
//main thread to update the UI.
[self.label performSelectorOnMainThread: @selector(setText:)
withObject: labelText];
}
//drain autorelease pool
[tempPool drain];
}
Thanks so much for you help Duncan, you've helped me before, very appreciative!
Although, when you say you believe my code is in a loop, are you talking about a common loop, eg. FOR loop? Because I'm not in a foor loop. Here is a brief description of whats happening:
- Scrollview Menu system waiting for a gestureRecogniser to be called on a button press. Depending on the press screen position changes the switch statement result.
- Inside the switch statement there is a fair amount of sequential processing, checking files on the net, etc. Because this is a large process, I've decided to move it to a - (void) function. Inside the function there are a few states where I want the menuLabel.text to be updated. These are the updates that aren't working.
Hopefully this description is clear enough.
Also, looking at your code example, ie. using the main thread for the UI and a seperate thread for processing. I'll give it a go. It seems to make sense.
Thanks so much for you help Duncan, you've helped me before, very appreciative!
Although, when you say you believe my code is in a loop, are you talking about a common loop, eg. FOR loop? Because I'm not in a foor loop. Here is a brief description of whats happening:
- Scrollview Menu system waiting for a gestureRecogniser to be called on a button press. Depending on the press screen position changes the switch statement result.
- Inside the switch statement there is a fair amount of sequential processing, checking files on the net, etc. Because this is a large process, I've decided to move it to a - (void) function. Inside the function there are a few states where I want the menuLabel.text to be updated. These are the updates that aren't working.
Hopefully this description is clear enough.
Also, looking at your code example, ie. using the main thread for the UI and a seperate thread for processing. I'll give it a go. It seems to make sense.
Thanks again
How are you waiting? Do you have a while loop, or sleep statements? Both of those would be bad. If you're waiting for a gesture recognizer, you shouldn't do anything special. It will call you when the user makes a gesture you are interested in.
You might need to post the function so we can see it.
Check out this password generator app that shows various techniques including using a data container singleton object to share data between objects in your project.
How are you waiting? Do you have a while loop, or sleep statements? Both of those would be bad. If you're waiting for a gesture recognizer, you shouldn't do anything special. It will call you when the user makes a gesture you are interested in.
You might need to post the function so we can see it.
So yeah, there is no looping going on. Only a very sequential process, which is passed between functions just to clean up the code a little.
As I mentioned at the beginning though, there is an indicator animating during the bulk of the processing, but I wouldn't think that would cause anything.
Thanks Duncan, I did what you said and setup the process as a new thread, and then when it came to changing the UILabel text, I used the mainThread. Works well.
Still curious as to why there was a problem in the first place, but I'm happy it's working.