How to pass arguments when calling function with t

2019-01-27 00:33发布

-(void)setX:(int)x andY:(int)y andObject:(Sprite*)obj
{
    [obj setPosition:CGPointMake(x,y)];
}

Now, I want to call above method, using following timer.

[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector() userInfo:nil repeats:NO];

What to set Here?

How to Pass arguments? (as per my knowledge - selector specifies only the method to invoke)

7条回答
Evening l夕情丶
2楼-- · 2019-01-27 00:52

You can pass an NSDictionary*, or some other object, as the userInfo and put the arguments in that.

查看更多
成全新的幸福
3楼-- · 2019-01-27 00:54

If you use a target-action timer, you can't have the timer directly call an arbitrary method. A timer's action must have a very specific signature. You can pass additional data in the userinfo dictionary and have the timer's action call the method you ultimately want, or you can use the invocation form as Dave said. Personally, I usually do the former, because I find NSInvocations to be annoying and setting one up can actually take more code than just writing an intermediary method.

查看更多
霸刀☆藐视天下
4楼-- · 2019-01-27 00:55

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.

查看更多
贼婆χ
5楼-- · 2019-01-27 00:58

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.

查看更多
混吃等死
6楼-- · 2019-01-27 01:02

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.

查看更多
爷、活的狠高调
7楼-- · 2019-01-27 01:05

Create dictionary with those arguments and pass that dictionary with timer userinfo. That will solve your problem

查看更多
登录 后发表回答