0

Where this:

distanceTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(applyShot:newPositionOne.x with:newPositionOne.y) userInfo:nil repeats:NO];

^^ This doesn't work.

Must equal this

[self applyShot:newPositionOne.x with:newPositionOne.y];

I basically need a delay before running this method, and it passes the variables because they'll be different by the time the method runs, so it has to remember them somehow.

However, I cannot for the life of me figure out how to pass variables in an @selector.

I've done it before with button.tag for example, but never for this.

Any help will be appreciated, thank you.

I understand I can just set global variables, but is is possible to pass them?

user2415313
  • 101
  • 1
  • 10

2 Answers2

2

Ok so there a couple things that you can do. You are correct, it is difficult to pass variables into an @selector() declaration. Here are two options:

1) call a different method (defined in your class) that handles the variables. For example:

distanceTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(applyShot) userInfo:nil repeats:NO];

- (void)applyShot
{
    // manipulate variables and do your logic here
}

2) Pass a dictionary into the userInfo argument of:

scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:

This dictionary can look like this:

NSDictionary *params = @{@"newXPosition: @(90), @""newYPosition: @(100)"};

Then just change your applyShot: method to take in an NSDictionary argument, and then parse through the dictionary there to find the relevant values and "apply the shot."

Brian Sachetta
  • 3,319
  • 2
  • 34
  • 45
  • The problem I really have is that it's to simulate `distance travelled by a bullet` so they press fire, one second later you see an impact. However, if they fire another shot before that one has hit, it will render the latest shot `posX & posY` therefore removing where the first shot was intended. I think the dictionary will be my best bet, however, will it account for this problem? – user2415313 Feb 10 '15 at 14:52
  • That sounds like a new question. It sounds like you might want to rethink your design. Having one posX and one posY variable can really never satisfy the locations of multiple bullets. Hard to tell, however, with the amount of code shown. I'd recommend asking a new question for the question you just listed in the comment above. – Brian Sachetta Feb 10 '15 at 15:02
  • The positions are added as nodes to the background on positions saved when the shot was fired, this has worked perfectly until I'm now implementing trajectory and velocity into the equation. However, the dispatch method has allowed me to continue with my current design thankfully. Thanks for you answers and appreciate the explanation. – user2415313 Feb 10 '15 at 15:10
1

A selector is not a packaged method. A selector is just the name of a message. You can think of it as a string (it used to be implemented as a string).

The traditional way to address this is with an NSInvocation which packages up a complete method call, not just the name of the message. That's well covered by Arguments in @selector. The other way to handle it is to package your options into the userInfo and change your method to read its parameters from that.

But typically the better solution today is to use dispatch_after instead:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC),
               dispatch_get_main_queue(),
               ^(void){
                   [self applyShot:newPositionOne.x with:newPositionOne.y];
                });
Community
  • 1
  • 1
Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Works perfectly, thank you. Is this the preferred method to use, or should I choose the dictionary path? – user2415313 Feb 10 '15 at 15:02
  • `dispatch_after` is now the preferred approach in most cases. `NSTimer` is a powerful tool, but has mostly been replaced by the `dispatch_` functions in GCD. – Rob Napier Feb 10 '15 at 15:03