在 Objective C 中使用计时器调用函数时如何传递参数
-(void)setX:(int)x andY:(int)y andObject:(Sprite*)obj
{
[obj setPosition:CGPointMake(x,y)];
}
现在,我想使用以下计时器调用上面的方法。
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector() userInfo:nil repeats:NO];
这里要设置什么?
如何传递参数? (据我所知 - 选择器仅指定要调用的方法)
-(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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您需要使用
+[NSTimer ScheduledTimerWithTimeInterval:inspiration:repeats:]
代替。默认情况下,用于触发计时器的选择器采用一个参数。如果您需要除此之外的其他内容,则必须创建 NSIncation 对象,计时器将使用该对象。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.如果您有一组相当复杂的参数想要用来调用该方法,我建议将参数捕获到保存配置的东西中,并且可以根据该配置执行任何需要执行的操作
...像这样的接口:
PositionSetter.h:
PositionSetter.m:
用法非常简单:
虽然代码多了一点,但生成的实现将足够快——可能比 NSInitation 更快,但足够快,因为这会导致绘图——而且更加灵活。我可以很容易地看到将上述内容重构为驱动,例如 CoreAnimation。
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:
PositionSetter.m:
Usage is quite straightforward:
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.
摘自 Matt Ball 的答案:
Copied from an answer by Matt Ball:
如果您使用目标操作计时器,则不能让计时器直接调用任意方法。计时器的操作必须具有非常具体的签名。您可以在 userinfo 字典中传递附加数据,并让计时器的操作调用您最终想要的方法,或者您可以使用 Dave 所说的调用形式。就我个人而言,我通常采用前者,因为我发现 NSInitations 很烦人,而且设置它实际上比仅仅编写中间方法需要更多的代码。
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.
您可以传递 NSDictionary* 或其他一些对象作为 userInfo 并将参数放入其中。
You can pass an NSDictionary*, or some other object, as the userInfo and put the arguments in that.
作为 NSTimer 的替代方案,在 iOS 4.0+ 和 10.6+ 上,您可以使用 Grand Central Dispatch 和调度源来使用块来执行此操作。 Apple 在其 并发编程指南:
然后,您可以使用如下代码设置一秒计时器事件:
只要您存储并在完成后释放计时器即可。这甚至可以让您使用并发队列而不是上面使用的主队列来触发计时器在后台线程上执行项目。
这可以避免装箱和拆箱参数的需要。
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:
You could then set up a one-second timer event using code like the following:
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