Passing parameters to the method called by a NSTimer

Objective CCocoa TouchSelectorNstimer

Objective C Problem Overview


How can I pass a parameter to the method called by a NSTimer? My timer looks like this:

[NSTimer scheduledTimerWithTimeInterval:4 target:self selector:@selector(updateBusLocation) userInfo:nil repeats:YES];

and I want to be able to pass a string to the method updateBusLocation. Also, where am supposed to define the method updateBusLocation? In the same .m file that I create the timer?

EDIT:

Actually I am still having problems. I am getting the error message:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[MapKitDisplayViewController updateBusLocation]: unrecognized selector sent to instance 0x4623600'

Here is my code:

- (IBAction) showBus {

//do something

[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateBusLocation) userInfo:txtFieldData repeats:YES];
[txtFieldData release];
 }


 - (void) updateBusLocation:(NSTimer*)theTimer
 {
      NSLog(@"timer method was called");
      NSString *txtFieldData = [[NSString alloc] initWithString:(NSString*)[theTimer userInfo]];
if(txtFieldData == busNum.text) {
	//do something else
    }
    }

EDIT #2: Never mind your example code works fine thanks for the help.

Objective C Solutions


Solution 1 - Objective C

You need to define the method in the target. Since you set the target as 'self', then yes that same object needs to implement the method. But you could have set the target to anything else you wanted.

userInfo is a pointer that you can set to any object (or collection) you like and that will be passed to the target selector when the timer fires.

Hope that helps.

EDIT: ... Simple Example:

Set up the timer:

    NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:2.0 
                              target:self 
                              selector:@selector(handleTimer:) 
                              userInfo:@"someString" repeats:NO];

and implement the handler in the same class (assuming you're setting the target to 'self'):

- (void)handleTimer:(NSTimer*)theTimer {
 
   NSLog (@"Got the string: %@", (NSString*)[theTimer userInfo]);
 
}

Solution 2 - Objective C

You can pass your arguments with userInfo:[NSDictionary dictionaryWithObjectsAndKeys:parameterObj1, @"keyOfParameter1"];

A simple example:

[NSTimer scheduledTimerWithTimeInterval:3.0
                                 target:self
                               selector:@selector(handleTimer:)
                               userInfo:@{@"parameter1": @9}
                                repeats:NO];

- (void)handleTimer:(NSTimer *)timer {
    NSInteger parameter1 = [[[timer userInfo] objectForKey:@"parameter1"] integerValue];
}

Solution 3 - Objective C

For Swift 4.0:

You can have a function with any parameters you want and use the "scheduledTimer" block to execute the code you need to repeat.

func someFunction(param1: Int, param2: String) {
    
    let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
        print(param1)
        print(param2)
    }
}

Be careful to call timer.invalidate() when you finish to prevent it from running continuously.

Solution 4 - Objective C

For Swift do like this,

For example you wants to send UILabel with NSTimer

override func viewDidLoad() {
    super.viewDidLoad()

    var MyLabel = UILabel()
    NSTimer.scheduledTimerWithTimeInterval(2, target: self, selector: Selector("callMethod:"), userInfo: MyLabel, repeats: false)
}


 func callMethod(timer:NSTimer){
	
	var MyLabel:UILabel = timer.userInfo as UILabel

}

Solution 5 - Objective C

Additional example in Swift using Dictionary literal for passing parameters to the method called by NSTimer:

override func viewDidLoad() {
    super.viewDidLoad()

    let dictionary: [String : AnyObject] = ["first element" : "Jordan",
                                            "second element" : Int(23)]

    NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(0.41),
                                           target: self,
                                           selector: "foo:",
                                           userInfo: dictionary,
                                           repeats: false)
}

func foo(timer: NSTimer) {
        let dictionary: [String : AnyObject] = timer.userInfo! as! [String : AnyObject]
        let firstElement: String = dictionary["first element"] as! String
        let secondElement: Int = dictionary["second element"] as! Int
        print("\(firstElement) - \(secondElement)")
}

Solution 6 - Objective C

Not a direct answer to the question but since i ran into this while searching and i needed something different it may help someone. I wanted to call a funciton in a helper class, that i needed to pass in the UIViewController, rather than passing it with the userinfo which would not allow me to call the function manually elsewhere i created another function which the timer would call and called the function that i was interested in from there. A workaround that helped.

Timer.scheduledTimer(timeInterval: 4, target: self, selector: #selector(self.timerFired), userInfo: nil, repeats:true);

func timerFired() {

myFunction(controller: self)

}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbubsterView Question on Stackoverflow
Solution 1 - Objective CFiroze LafeerView Answer on Stackoverflow
Solution 2 - Objective COleh KudinovView Answer on Stackoverflow
Solution 3 - Objective CGeorge LeonidasView Answer on Stackoverflow
Solution 4 - Objective CMohammad Zaid PathanView Answer on Stackoverflow
Solution 5 - Objective CKing-WizardView Answer on Stackoverflow
Solution 6 - Objective CSam BingView Answer on Stackoverflow