How to pass arguments when calling function with timer in objective c

后端 未结 7 1513
我寻月下人不归
我寻月下人不归 2020-12-20 00:02
-(void)setX:(int)x andY:(int)y andObject:(Sprite*)obj
{
    [obj setPosition:CGPointMake(x,y)];
}

Now, I want to call above method, using following

相关标签:
7条回答
  • 2020-12-20 00:20

    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.

    0 讨论(0)
  • 2020-12-20 00:22

    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.

    0 讨论(0)
  • 2020-12-20 00:27

    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];
        }
    
    0 讨论(0)
  • 2020-12-20 00:29

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

    0 讨论(0)
  • 2020-12-20 00:31

    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.

    0 讨论(0)
  • 2020-12-20 00:37

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

    0 讨论(0)
提交回复
热议问题