20

I am new to iOS development, I have plain objective -c class "MoneyTimer.m" for running timer, from there i want to update the an UI label with the changing value of timer. I want to Know how to access the UI element from non UI thread ? I am Using Xcode 4.2 and storyboarding.

In blackberry simply by getting the event lock one can update the UI's from non UI thread.

//this the code from MyTimerClass

 {...
    if(nsTimerUp == nil){

        nsTimerUp = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:@selector(countUpH) userInfo:nil repeats: YES];
 ...}

(void) countUpH {

sumUp = sumUp + rateInSecH;
 **//from here i want to update the UI label **
...
}
Dobroćudni Tapir
  • 3,082
  • 20
  • 37
Jitendra kumar jha
  • 243
  • 1
  • 2
  • 12
  • 1
    You can update ui from all main thread, updating of UI from background thread only creates issue. – rishi Jun 28 '12 at 10:11

5 Answers5

34

This is the quickest and simplest way to do it is:

- (void) countUpH{

   sumUp = sumUp + rateInSecH;
   //Accessing UI Thread
   [[NSOperationQueue mainQueue] addOperationWithBlock:^{

      //Do any updates to your label here
      yourLabel.text = newText;

   }];
}

If you do it this way you don't have to switch to a different method.

Hope this helps.

Sam

Salman Zaidi
  • 9,342
  • 12
  • 44
  • 61
shoughton123
  • 4,255
  • 3
  • 21
  • 23
  • @shoughton123, can I even call `[[NSOperationQueue mainQueue] addOperationWithBlock:...` within a methode which runs in the background? Thanks – JFS Sep 04 '13 at 13:53
  • Indeed you can, sorry for the slow reply! – shoughton123 Sep 10 '13 at 09:10
  • See http://stackoverflow.com/a/10509159/1277350 for detail on addOperationWithBlock vs performSelectorOnMainThread behaviour. – LordParsley Jul 30 '14 at 14:29
3

Your question doesn't give much info or detail so it is hard to know exactly what you need to do (e.g. if there is a "thread" issue at all, etc.).

At any rate, assuming your MoneyTimer instance has a reference to the current viewController you can use performSelectorOnMainThread.

//

- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
spring
  • 18,009
  • 15
  • 80
  • 160
  • sorry for lack of details, In fact I have a Timer class which is inheriting from NSObject, from there i want to update a UILabel placed as an property into one of my ViewController. Now I am not able to access the UILabel form my Timer class. – Jitendra kumar jha Jun 28 '12 at 10:30
  • Why can't you access it? Add a delegate property to your Timer class and set the viewController you want to communicate with as the delegate when you create the Timer instance. Then call a method on the delegate to update the label. That is a standard iOS design pattern - good to get to know it. And just for fun, are you doing other work in the Timer class? Maybe you are getting too object-oriented ;-) – spring Jun 28 '12 at 10:35
3

The proper way is this:

- (void) countUpH  {
   sumUp = sumUp + rateInSecH;
   //Accessing UI Thread
   dispatch_async(dispatch_get_main_queue(), ^{

   //Do any updates to your label here
    yourLabel.text = newText;
   });
}
RawMean
  • 8,374
  • 6
  • 55
  • 82
2

I've done something identical in the past.

I used a function to set the label text:

- (void)updateLabelText:(NSString *)newText {
    yourLabel.text = newText;
}

and then called this function on the main thread with performSelectorOnMainThread

NSString* myText = @"new value";
[self performSelectorOnMainThread:(@selector)updateLabelText withObject:myText waitUntilDone:NO];
BBog
  • 3,630
  • 5
  • 33
  • 64
1

Assuming that label lives in the same class:

    if(nsTimerUp == nil){
        nsTimerUp = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:@selector(countUpH) userInfo:nil repeats: YES];
    [self performSelectorOnMainThread:@selector(updateLabel)
                                           withObject:nil
                                        waitUntilDone:NO];

    }

-(void)updateLabel {
    self.myLabel.text = @"someValue";
}
LJ Wilson
  • 14,445
  • 5
  • 38
  • 62