基于可变数量的参数构建NSString

时间:2014-05-06 22:18:52

标签: ios objective-c nsstring variadic-functions stringwithformat

我的函数采用字典参数和可变数量的NSString变量。所有这些组合都放在[NSString stringWithFormat:]方法中,并作为NSURLRequest返回。该方法如下所示:

- (NSURLRequest *)buildPath:(NSString *)stringPath attributes:(NSString *)attribute, ...
{
    va_list list;
    NSString *eachObject;
    NSMutableArray *args = [NSMutableArray array];

    [args addObject:attribute];
    va_start(list, attribute);
    while ((eachObject = va_arg(list, NSString *))) {
        [args addObject:eachObject];
    }
    va_end(list);

    NSString *listOfAttributes = [args componentsJoinedByString:@", "];
    NSString *pathURL = _requestString[stringPath];
    NSString *path = [NSString stringWithFormat:pathURL, listOfAttributes];

    NSURL *url = [NSURL URLWithString:path];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    return request;
}

这就是我调用方法时的样子:

NSURLRequest *request = [_venueService buildPath:@"categories"
                                          attributes:_venueService.clientID, _venueService.clientSecret, _venueService.todaysDate, nil];

当我运行该程序时,它崩溃了。当我退出listOfAttributes时,它会给我:

client_id, client_secret, 20140507

这是我的3个参数,这是正确的,stringPath(当我在我的程序中实际调用它时,我写stringPath[@"categories"]),当我NSLog给我时:

https://api.foursquare.com/v2/venues/categories?client_id=%@&client_secret=%@&v=%@

所以,我的问题是,为什么这两个字符串在[NSString stringWithFormat:]中合并会导致问题?

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:4)

正如贾斯汀指出的那样,有一种更简单的方法可以做到这一点。 NSString有一个-initWithFormat:arguments:方法,可以完全按照你的意愿执行。

此外,您的方法名称有一些问题:

  1. 命名约定 - 您应在方法名称中指明其用途(创建URL请求)
  2. 您正在为路径传入(NSDictionary *),但在使用它时将其强制转换为(NSString *)。这两个对象不兼容。我想在复制粘贴代码时这可能是一个错字?
  3. 也可以使用与NSString' s + stringWithFormat:method相同的调用约定。
  4. 考虑到上述所有情况,该方法变得类似(没有错误检查):

    - (NSURLRequest  *)URLRequestWithFormat:(NSString *)format, ... {
        va_list arguments;
        va_start(arguments, format);
        NSString *urlPath = [[NSString alloc] initWithFormat:format arguments:arguments];
        va_end(arguments);
        NSURL *url = [NSURL URLWithString:urlPath];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        return request;
    }
    

    这样可以通过以下方式调用:

    NSURLRequest *request = [self URLRequestWithFormat:@"https://api.foursquare.com/v2/venues/categories/client_id=%@&client_secret=%@&v=%@", @"One",@"Two",@"Three"];
    NSLog(@"Request: %@", request);
    

    输出:

    2014-05-07 09:52:30.645 Test[5888:60b] Request: <NSURLRequest: 0x8c64f30> { URL: https://api.foursquare.com/v2/venues/categories/client_id=One&client_secret=Two&v=Three }
    

答案 1 :(得分:2)

您可能需要阅读-[NSString initWithFormat:arguments:]的文档。该方法接受va_list参数,可能会执行您想要的操作。

示例代码不起作用的原因是因为stringWithFormat需要为格式字符串中显示的每个占位符分别设置一个参数。您的格式字符串看起来像包含三个%@占位符,但您只传递一个参数listOfAttributes

答案 2 :(得分:1)

stringPath中的格式指定应该有3个参数,但是你只提供一个 - listOfAttributes。

listOfAttributes是一个参数而不是3。