Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
($1.99)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 06-09-2011, 06:09 AM   #1 (permalink)
Registered Member
 
Join Date: Jan 2011
Location: Brisbane, Australia
Posts: 14
blang is on a distinguished road
Default UILabel Text changes only in new thread

Hi all,

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.

Code:
- (void)changeLabel:(NSString *)text
{
    menuLabel.text = text;
}
This is called using:

Code:
    [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.
blang is offline   Reply With Quote
Old 06-09-2011, 08:30 AM   #2 (permalink)
Nuisance Developer
 
Join Date: Jul 2009
Location: Italy
Posts: 4,691
dany_dev is on a distinguished road
Default

you call it

[self changeLabel:@"sss"];

and doesn't work?
Have you tried to use breakpoints to see if code run? have you tried to see if menuLabel is not nil?
__________________
dany_dev is offline   Reply With Quote
Old 06-09-2011, 08:47 AM   #3 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 6,003
Duncan C has a spectacular aura about
Default Do NOT change UI except from the main thread.

Quote:
Originally Posted by blang View Post
Hi all,

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.

Code:
- (void)changeLabel:(NSString *)text
{
    menuLabel.text = text;
}
This is called using:

Code:
    [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];
}
__________________
Regards,

Duncan C
WareTo

Check out our apps in the Apple App store


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.

See this tutorial on using UIView animations and layer animations:

See this thread on generating random, non-repeating text

Check out a very cool Macintosh Kaleidoscopes app called ScopeWorks that we released to the Mac App store.
Duncan C is offline   Reply With Quote
Old 06-09-2011, 06:48 PM   #4 (permalink)
Registered Member
 
Join Date: Jan 2011
Location: Brisbane, Australia
Posts: 14
blang is on a distinguished road
Default

Quote:
Originally Posted by Duncan C View Post
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 again
blang is offline   Reply With Quote
Old 06-09-2011, 07:14 PM   #5 (permalink)
Cocoa Junkie
 
Duncan C's Avatar
 
Join Date: Dec 2008
Location: Northern Virginia
Posts: 6,003
Duncan C has a spectacular aura about
Default

Quote:
Originally Posted by blang View Post
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.
__________________
Regards,

Duncan C
WareTo

Check out our apps in the Apple App store


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.

See this tutorial on using UIView animations and layer animations:

See this thread on generating random, non-repeating text

Check out a very cool Macintosh Kaleidoscopes app called ScopeWorks that we released to the Mac App store.
Duncan C is offline   Reply With Quote
Old 06-09-2011, 07:48 PM   #6 (permalink)
Registered Member
 
Join Date: Jan 2011
Location: Brisbane, Australia
Posts: 14
blang is on a distinguished road
Default

Quote:
Originally Posted by Duncan C View Post
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.
Hi, Sorry 'waiting' is the wrong word, I'm using:

Code:
- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer {
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
blang is offline   Reply With Quote
Old 06-11-2011, 08:17 AM   #7 (permalink)
Registered Member
 
Join Date: Jan 2011
Location: Brisbane, Australia
Posts: 14
blang is on a distinguished road
Default Got it working

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.

Thanks again.
blang is offline   Reply With Quote
Reply

Bookmarks

Tags
change, text, thread, uilabel

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 317
7 members and 310 guests
chemistry, Dnnake, iOS.Lover, jenniead38, lendo, Leslie80, pbart
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 175,664
Threads: 94,120
Posts: 402,898
Top Poster: BrianSlick (7,990)
Welcome to our newest member, Leslie80
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 02:21 AM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0