Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Arguments in @selector

Is there any way that I can pass arguments in selector?

example: I have this method

- (void)myMethod:(NSString*)value1 setValue2:(NSString*)value2{  } 

and I need to call this function through a selector passing two arguments.

[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(/*my method*/) userInfo:nil repeats:YES]; 

How can I do this?

like image 336
isiaatz Avatar asked Aug 28 '09 22:08

isiaatz


People also ask

How do you pass parameters in OBJC func?

The action method must take one parameter, namely the sender (which in this case will be the button). If the action method needs more information at the time that it is called, you must provide that information in some other way, e.g. as an instance property that the action method can access when it is called.

What is selector() in Swift?

Use Selectors to Arrange Calls to Objective-C Methods In Objective-C, a selector is a type that refers to the name of an Objective-C method. In Swift, Objective-C selectors are represented by the Selector structure, and you create them using the #selector expression.

What is a selector in Objective-C?

In Objective-C, selector has two meanings. It can be used to refer simply to the name of a method when it's used in a source-code message to an object. It also, though, refers to the unique identifier that replaces the name when the source code is compiled. Compiled selectors are of type SEL .


2 Answers

You could use the NSTimer method:

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds                                  invocation:(NSInvocation *)invocation                                     repeats:(BOOL)repeats; 

Instead, since an NSInvocation object will allow you to pass arguments; an NSInvocation object is, as the docs define it:

an Objective-C message rendered static, that is, it is an action turned into an object.

Whilst creating an NSTimer object using a selector requires the format of the method being:

- (void)timerFireMethod:(NSTimer*)theTimer 

An NSInvocation allows you to set the target, the selector, and the arguments that you pass in:

SEL selector = @selector(myMethod:setValue2:);  NSMethodSignature *signature = [MyObject instanceMethodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setSelector:selector];  NSString *str1 = @"someString"; NSString *str2 = @"someOtherString";  //The invocation object must retain its arguments [str1 retain]; [str2 retain];  //Set the arguments [invocation setTarget:targetInstance]; [invocation setArgument:&str1 atIndex:2]; [invocation setArgument:&str2 atIndex:3];  [NSTimer scheduledTimerWithTimeInterval:0.1 invocation:invocation repeats:YES]; 

Where MyObject is the class that myMethod:setValue2: is declared and implemented on – instanceMethodSignatureForSelector: is a convenience function declared on NSObject which returns an NSMethodSignature object for you, to be passed to NSInvocation.

Also, to note, with setArgument:atIndex:, the indices for arguments to be passed to the method set as the selector start at index 2. From the docs:

Indices 0 and 1 indicate the hidden arguments self and _cmd, respectively; you should set these values directly with the setTarget: and setSelector: methods. Use indices 2 and greater for the arguments normally passed in a message.

like image 124
Alex Rozanski Avatar answered Nov 10 '22 18:11

Alex Rozanski


For scheduledTimerWithTimeInterval:, the selector you pass can only have one argument. Further, its one argument must be an NSTimer * object. In other words, the selector must take the following form:

- (void)timerFireMethod:(NSTimer*)theTimer 

What you could do is store the arguments in the userInfo dictionary and call the selector you want from the timer callback:

- (void)startMyTimer {     /* ... Some stuff ... */     [NSTimer scheduledTimerWithTimeInterval:0.1                                       target:self                                     selector:@selector(callMyMethod:)                                     userInfo:[NSDictionary dictionaryWithObjectsAndKeys:someValue,                         @"value1", someOtherValue, @"value2", nil]                                      repeats:YES]; }  - (void)callMyMethod:(NSTimer *)theTimer {     NSString *value1 = [[theTimer userInfo] objectForKey:@"value1"];     NSString *value2 = [[theTimer userInfo] objectForKey:@"value2"];     [self myMethod:value1 setValue2:value2]; } 
like image 39
Matt Ball Avatar answered Nov 10 '22 18:11

Matt Ball