使用ARC将可变参数从一种方法传递到另一种方法

时间:2011-12-14 05:08:46

标签: objective-c

我正在尝试将一个可变参数(NSString *)从一个方法传递给另一个方法,如下例所示:


- (NSURL *)urlForId:(NSString *)aId params:(NSDictionary *)aParams parts:(NSString *)aPart, ... {
    // ... do something with parts
}

- (NSURL *)specialUrlForId:(NSString *)aId params:(NSDictionary *)aParams parts:(NSString *)aPart, ... {
    va_list arg;
    va_start(args, aPart);
    [self urlForId:aId params:aParam parts:args];
    va_end(args);
}

尝试传递args时问题就开始了。 ARC抱怨从va_list(char *)到NSString *的隐式转换。我已经尝试了一切来使这个工作。

如果我将va_list传递给[NSString stringWithFormat:...],那么同样的技术也会有效,所以我不明白为什么它不能在这里工作。

任何帮助表示赞赏。

1 个答案:

答案 0 :(得分:3)

您的urlForId:params:parts:方法希望parts:键盘后的第一个参数为NSString*,但您传递va_list。那些是不同的类型。将va_list变量作为函数参数传递并不会将其神奇地扩展为所有原始参数。在封面下,va_list实际上只是指向堆栈框架的指针,而这就是所有传递的内容。

您真正需要做的是将urlForId:params:parts:部分列出部分列表,并直接从specialUrlForId:params:parts:调用该因素部分。大概你的urlForId:params:parts:方法看起来像这样:

- (NSURL *)urlForId:(NSString *)aId params:(NSDictionary *)aParams parts:(NSString *)aPart, ...
{
    va_list ap;
    va_start(ap, aPart);

    // loop over the variable arguments, starting with aPart, perhaps
    // stopping when you find nil.
    while (aPart != nil) {
        doSomething(aPart);
        aPart = va_arg(ap, NSString *);
    }

    va_end(ap);

    return someUrl;
}

所以你在这里做的是将va_start之后和va_end之前的部分移动到采用va_list参数的方法:

- (NSURL *)urlForId:(NSString *)aId params:(NSDictionary *)aParams arguments:(va_list)ap
{
    // loop over the variable arguments, starting with aPart, perhaps
    // stopping when you find nil.
    while (aPart != nil) {
        doSomething(aPart);
        aPart = va_arg(ap, NSString *);
    }
    return someUrl;
}

然后,您同时urlForId:params:parts:specialUrlForId:params:parts:调用这个新的urlForId:params:arguments:方法:

- (NSURL *)urlForId:(NSString *)aId params:(NSDictionary *)aParams parts:(NSString *)aPart, ...
{
    va_list ap;
    va_start(ap, aPart);
    NSURL *url = [self urlForId:aId params:aParams arguments:ap];
    va_end(ap);
    return url;
}

- (NSURL *)specialUrlForId:(NSString *)aId params:(NSDictionary *)aParams parts:(NSString *)aPart, ...
{
    va_list ap;
    va_start(ap, aPart);
    NSURL *url = [self urlForId:aId params:aParams arguments:ap];
    va_end(ap);
    return url;
}