@selector的多个参数

时间:2013-03-12 13:46:44

标签: ios objective-c selector nsinvocation

我正在用目标C创建一个游戏,我被一个问题所阻止:我有一个警告,要求在@selector上传递多个变量。 我想要做的是在我的UIViewController中调用一个方法但是在延迟之后。所以我尝试制作第一种方法,在延迟之后调用另一种方法:

-(void)AnimationCoinInitWith_x:(int)x y:(int)y w:(int)w h:(int)h afterDelay:(NSTimeInterval)t
{
    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
                                [self methodSignatureForSelector:@selector(AnimationCoinCopyInitWith_x:y:w:h:)]];
    [invocation setTarget:self];
    [invocation setSelector:@selector(AnimationCoinCopyInitWith_x:y:w:h:)];
    [invocation setArgument:x atIndex:1];
    [invocation setArgument:y atIndex:2];
    [invocation setArgument:w atIndex:3];
    [invocation setArgument:h atIndex:4];
    [NSTimer scheduledTimerWithTimeInterval:t invocation:invocation repeats:NO];
}

-(void)AnimationCoinCopyInitWith_x:(int)x y:(int)y w:(int)w h:(int)h
{
    UIImageView* imageViewCoin = [[UIImageView alloc] initWithFrame:CGRectMake(x, y, w, h)];
    [imageViewCoin setAnimationImages:images];
    [imageViewCoin setAnimationRepeatCount:1000];
    [imageViewCoin setAnimationDuration:(1/24)];
    [imageViewCoin startAnimating];
    [self addSubview:imageViewCoin];
    [imageViewCoin release];
}

但它不起作用,我不知道为什么。

感谢您的帮助!

2 个答案:

答案 0 :(得分:4)

在这里,您的问题是NSInvocation不会自动设置您需要的参数偏移量,并且所有objective-c方法都有两个不可见的参数(self_cmd) ,你必须将参数索引偏移2而不是1。

这里的另一个问题是你没有通过引用传递参数,所以你必须使用地址运算符(&):

[invocation setArgument:&x atIndex:2];
[invocation setArgument:&y atIndex:3];
[invocation setArgument:&w atIndex:4];
[invocation setArgument:&h atIndex:5];

一旦你这样做,上面的代码应该可以正常工作。

答案 1 :(得分:0)

作为一般规则,我们采用了避免NSInvocation的策略,除非绝对必要,因为代码往往难以阅读,易碎,并且在重构时会很头疼(以及错误的来源)。

此外,通过避免NSInvocation和使用简单的调用站点,编译器完全能够验证代码。

您可以使用“dispatch_after”模式:

    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
     [self animationCoinInitWith_x: ...];
    });

或者,如果你想坚持使用-performSelector:withObject:afterDelay :(我发现它更具可读性):

@interface Foo : NSObject
@end

@implementation Foo
- (void)invokeBlock:(dispatch_block_t)aBlock
{
    aBlock();
}

- (void)doIt:(int)x toIt:(int)y
{
    NSLog(@"%s %d %d", __PRETTY_FUNCTION__, x, y);
}
@end


int main(int argc, const char * argv[])
{
    @autoreleasepool {
        Foo* foo = [Foo new];
        dispatch_block_t block = ^{
            [foo doIt:10 toIt:10];
        };
        [foo performSelector:@selector(invokeBlock:) withObject:[block copy] afterDelay:5];
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

以上假设为ARC(因此,缺乏发布)。