Objective c 在Objective C中,有没有办法将整个参数列表传递给另一个方法?

Objective c 在Objective C中,有没有办法将整个参数列表传递给另一个方法?,objective-c,reflection,Objective C,Reflection,我希望能够以尽可能一般的方式将方法中接收到的所有参数传递给另一个方法 理想情况下,这可以通过传递字典或某些系统变量(类似于_cmd)来实现 换句话说,我正在寻找类似javascript中的参数数组的东西,或者任何允许我访问当前调用的方法的参数列表的东西 您可能想看看NSMethodSignature类文档。此类用于记录参数信息和方法返回值。我认为您要查找的是forwardInvocation:它会传递一个包含所需信息的NSInvocation对象NSInvocation还有一个很好的方法,名为i

我希望能够以尽可能一般的方式将方法中接收到的所有参数传递给另一个方法

理想情况下,这可以通过传递字典或某些系统变量(类似于_cmd)来实现


换句话说,我正在寻找类似javascript中的
参数
数组的东西,或者任何允许我访问当前调用的方法的参数列表的东西

您可能想看看NSMethodSignature类文档。此类用于记录参数信息和方法返回值。

我认为您要查找的是
forwardInvocation:
它会传递一个包含所需信息的
NSInvocation
对象
NSInvocation
还有一个很好的方法,名为
invokeWithTarget:
,它可以转发方法调用,就像直接调用它一样

运行时将调用
fowardInvocation:
,如果向对象发送了一条它没有方法的消息,前提是您还重写
methodSignatureForSelector:
,以便运行时可以创建NSInvocation对象

如果所有参数都是对象,则方法
forwardInvocation
的外观如下:

@implementation Forwarder

@synthesize friendObject;

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    return [self.friendObject methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    NSLog("Forwarding method: %@", [anInvocation selector]);

    NSMethodSignature *sig = [anInvocation methodSignature];

    // Get the juicy argument list info from [anInvocation methodSignature]
    // NOTE: Arguments 0 and 1 are for self and _cmd So we'll skip those.

    int numberOfArgs = [[anInvocation methodSignature] numberOfArguments];

    // Assuming all arguments are objects.
    id objPointer;
    NSMutableArray *argArray = [NSMutableArray array];

    for (int i = 2; i < numberOfArgs; i++) {
        [anInvocation getArgument:&objPointer atIndex:i];
        [argArray addObject:objPointer];
    }

    // Now argArray contains the array of all the arguments.
}

@end
@interface testreflectAppDelegate : NSObject <UIApplicationDelegate, ForwarderDelegate> {
    UIWindow *window;
}


@end

@implementation testreflectAppDelegate

@synthesize window;

- (BOOL)application:(UIApplication *)application 
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    [window makeKeyAndVisible];

    Forwarder *forwarder = [[[Forwarder alloc] init] autorelease];
    forwarder.delegate = self;
    forwarder.interfaceObject = self;


    [((id)forwarder) doFoo:[NSNumber numberWithInt:1] 
                   withBar:[NSNumber numberWithInt:2]];

    return YES;
}

- (void)doFoo:(NSNumber *)foo withBar:(NSNumber *)bar {
    NSLog(@"doFoo:withBar: called. Args: %d %d", [foo intValue], [bar intValue]);
}

- (void)doFoo:(NSNumber *)foo {
    NSLog(@"doFoo called. Args: %d", [foo intValue]);
}

- (void)selectorCalled:(SEL)selector withArguments:(NSArray *)args {
    NSLog(@"selectorCalled: %s with %d arguments", selector, [args count]);
    [self doFoo:[args objectAtIndex:0]];
}

@end
然后让实际的货代:

@interface Forwarder : NSObject {

  @private
    NSObject *interfaceObject;
    id<ForwarderDelegate> delegate;
}

// Some object whose methods we want to respond to.
@property (nonatomic, retain) NSObject *interfaceObject;
@property (nonatomic, retain) id<ForwarderDelegate> delegate;

@end

@implementation Forwarder

@synthesize interfaceObject;
@synthesize delegate;

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    return [interfaceObject methodSignatureForSelector:selector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {

    int numberOfArgs = [[anInvocation methodSignature] numberOfArguments];

    NSMutableArray *args = [NSMutableArray array];

    id ref;
    for (int i = 2; i < numberOfArgs; i++) {
        [anInvocation getArgument:&ref atIndex:i];
        [args addObject:ref];
    }

    // Call the method on the interface (original) object.
    if ([self.interfaceObject respondsToSelector:[anInvocation selector]]) {
        [anInvocation invokeWithTarget:self.interfaceObject];
    }

    [self.delegate selectorCalled:[anInvocation selector] withArguments:args];
}

@end

同样,此版本仅适用于id类型的参数。但是如果您使用上述类型编码,则可以处理其他类型。

所有这些都很好,但我正在寻找一种将参数作为数组访问的方法,这样我就可以将它们转发到一个不相关的方法。啊,我发现用完全通用的方法来处理要复杂得多。我已经更新了我的答案,告诉你如果这个方法的所有参数都是对象,你可以怎么做。不过,我还没有测试上面的代码,所以对此持保留态度。
@interface testreflectAppDelegate : NSObject <UIApplicationDelegate, ForwarderDelegate> {
    UIWindow *window;
}


@end

@implementation testreflectAppDelegate

@synthesize window;

- (BOOL)application:(UIApplication *)application 
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    [window makeKeyAndVisible];

    Forwarder *forwarder = [[[Forwarder alloc] init] autorelease];
    forwarder.delegate = self;
    forwarder.interfaceObject = self;


    [((id)forwarder) doFoo:[NSNumber numberWithInt:1] 
                   withBar:[NSNumber numberWithInt:2]];

    return YES;
}

- (void)doFoo:(NSNumber *)foo withBar:(NSNumber *)bar {
    NSLog(@"doFoo:withBar: called. Args: %d %d", [foo intValue], [bar intValue]);
}

- (void)doFoo:(NSNumber *)foo {
    NSLog(@"doFoo called. Args: %d", [foo intValue]);
}

- (void)selectorCalled:(SEL)selector withArguments:(NSArray *)args {
    NSLog(@"selectorCalled: %s with %d arguments", selector, [args count]);
    [self doFoo:[args objectAtIndex:0]];
}

@end
testreflect[3098:207] doFoo:withBar: called. Args: 1 2
testreflect[3098:207] selectorCalled: doFoo:withBar: with 2 arguments
testreflect[3098:207] doFoo called. Args: 1