-(void)setX:(int)x andY:(int)y andObject:(Sprite*)obj
{
[obj setPosition:CGPointMake(x,y)];
}
Now, I want to call above method, using following
You'll need to used +[NSTimer scheduledTimerWithTimeInterval:invocation:repeats:] instead. By default, the selector used to fire a timer takes one parameter. If you need something other than that, you have to create an NSInvocation object, which the timer will use instead.
If you have a fairly complex set of arguments that you want to use to invoke the method, I would recommend capturing the arguments into something that holds a configuration and can do whatever it is that needs doing based on that configuration...
Something with an interface like this:
PositionSetter.h:
@interface PositionSetter : NSObject
{
NSInteger x;
NSInteger y;
Sprite *target;
}
+ positionSetterWithX: (NSInteger) xPos y: (NSInteger) yPos sprite: (Sprite *) aSprite;
- (void) applyPosition;
@end
PositionSetter.m:
@interface PositionSetter()
@property(readwrite, nonatomic) NSInteger x;
@property(readwrite, nonatomic) NSInteger y;
@property(readwrite, nonatomic, retain) Sprite *target;
@end
@implementation PositionSetter
@synthesize x, y, target;
+ positionSetterWithX: (NSInteger) xPos y: (NSInteger) yPos sprite: (Sprite *) aSprite;
{
PositionSetter *positionSetter = [PositionSetter new];
positionSetter.x = xPos;
positionSetter.y = yPos;
positionSetter.target = aSprite;
return [positionSetter autorelease];
}
- (void) applyPosition;
{
[self.target setPosition:CGPointMake(self.x,self.y)];
}
@end
Usage is quite straightforward:
positionSetter = [PositionSetter positionSetterWithX: 42 y: 21 sprite: mySprite];
[positionSetter performSelector: @selector(applyPosition) withObject: nil afterDelay: 1.0];
While a tad more code, the resulting implementation will be fast enough -- probably faster than NSInvocation, but fast enough to be irrelevant given that this is gonna cause drawing -- and a heck of a lot more flexible. I could easily see refactoring the above into driving, say, CoreAnimation.
Copied from an answer by Matt Ball:
- (void)startMyTimer {
/* ... Some stuff ... */
NSDictionary *userDict;
userDict = [NSDictionary dictionaryWithObjectsAndKeys:someValue,
@"value1",
someOtherValue,
@"value2", nil];
[NSTimer scheduledTimerWithTimeInterval:0.1
target:self
selector:@selector(callMyMethod:)
userInfo:userDict
repeats:YES];
}
- (void)callMyMethod:(NSTimer *)theTimer {
NSString *value1 = [[theTimer userInfo] objectForKey:@"value1"];
NSString *value2 = [[theTimer userInfo] objectForKey:@"value2"];
[self myMethod:value1 setValue2:value2];
}
You can pass an NSDictionary*, or some other object, as the userInfo and put the arguments in that.
As an alternative to NSTimer, on iOS 4.0+ and 10.6+, you could use Grand Central Dispatch and dispatch sources to do this using a block. Apple has the following code for this in their Concurrency Programming Guide:
dispatch_source_t CreateDispatchTimer(uint64_t interval, uint64_t leeway, dispatch_queue_t queue, dispatch_block_t block)
{
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
if (timer)
{
dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), interval, leeway);
dispatch_source_set_event_handler(timer, block);
dispatch_resume(timer);
}
return timer;
}
You could then set up a one-second timer event using code like the following:
dispatch_source_t newTimer = CreateDispatchTimer(1ull * NSEC_PER_SEC, (1ull * NSEC_PER_SEC) / 10, dispatch_get_main_queue(), ^{
[self setX:someValue andY:otherValue andObject:obj];
});
as long as you store and release your timer when done. This can even let you trigger a timer to execute items on a background thread by using a concurrent queue instead of the main queue used above.
This can avoid the need for boxing and unboxing arguments.
Create dictionary with those arguments and pass that dictionary with timer userinfo. That will solve your problem