Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Instance Variables from NSTimer selector

Tags:

objective-c

Firstly newbie question: What's the difference between a selector and a method?

Secondly newbie question (who would have thought): I need to loop some code based on instance variables and pause between loops until some condition (of course based on instance variables) is met. I've looked at sleep, I've looked at NSThread. In both discussions working through those options many asked why don't I use NSTimer, so here I am.

Ok so it's simple enough to get a method (selector? ) to fire on a schedule. Problem I have is that I don't know how to see instance variables I've set up outside the timer from within the code NSTimer fires. I need to see those variables from the NSTimer selector code as I 1) will be updating their values and 2) will set labels based on those values.

Here's some code that shows the concept… eventually I'd invalidate the timers based on myVariable too, however I've excluded that for code clarity.

MyClass *aMyClassInstance = [MyClass new]; 
[aMyClassInstance setMyVariable:0];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(doStuff) userInfo:nil repeats:YES];
[NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(doSomeOtherStuff) userInfo:nil repeats:YES];

- (void) doStuff {
        [aMyClassInstance setMyVariable:11]; //  don't actually have access to set aMyClassInstance.myVariable
        [self updateSomeUILabel:[NSNumber numberWithInt:aMyClassInstance.myVariable]];  // don't actually have access to aMyClassInstance.myVariable
}

- (void) doSomeOtherStuff {
        [aMyClassInstance setMyVariable:22]; //  don't actually have access to set aMyClassInstance.myVariable
        [self updateSomeUILabel:[NSNumber numberWithInt:aMyClassInstance.myVariable]];  // don't actually have access to aMyClassInstance.myVariable
}

- (void) updateSomeUILabel:(NSNumber *)arg{
        int value = [arg intValue];
         someUILabel.text = [NSString stringWithFormat:@"myVariable = %d", value];  // Updates the UI with new instance variable values
}
like image 519
Timbo Avatar asked Feb 27 '23 22:02

Timbo


1 Answers

You can use the userInfo parameter to transmit arbitrary object. In this case, you pass aMyClassInstance as userInfo:

MyClass *aMyClassInstance = [MyClass new]; 
[aMyClassInstance setMyVariable:0];
[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(doStuff) userInfo:aMyClassInstance repeats:YES];

In the timer callback (which MUST takes a parameter), you get back the userInfo from the timer and cast it:

- (void) doStuff:(NSTimer *)timer {
    MyClass *instance = (MyClass *)[timer userInfo];
    [instance setMyVariable:11];
    [self updateSomeUILabel:[NSNumber numberWithInt:instance.myVariable]];
}

The neat thing is that the timer retains the userInfo parameter.

like image 71
Laurent Etiemble Avatar answered Mar 08 '23 07:03

Laurent Etiemble