如何在Objective-C中创build可变参数方法

也许这对大多数人来说显然是简单的,但是请你举个例子来说明如何创build类似的方法(在Objective-C中)和C中的函数来创build像NSStringstringWithFormat:或者NSLog()

只是提醒一下:

 [NSString stringWithFormat:@"example tekst %i %@ %.2f",122,@"sth",3.1415"]; NSLog(@"account ID %i email %@",accountID,email); 

我想创build类似于NSString的方法stringWithFormat:NSURL - urlWithFormat

先谢谢你。

一般来说,这些被称为“可变参数函数”(或方法,因为它)。

要创build这个,只需结束你的方法声明, ... ,如

 - (void)logMessage:(NSString *)message, ...; 

在这一点上,你可能想把它包装在一个类似printf的函数中,因为实现其中一个从头开始尝试。

 - (void)logMessage:(NSString *)format, ... { va_list args; va_start(args, format); NSLogv(format, args); va_end(args); } 

注意使用NSLogv而不是NSLog ; 考虑NSLog(NSString *, ...); vs NSLogv(NSString *, va_list); ,或者如果你想要一个string; initWithFormat:arguments:NSString *


另一方面,如果你不使用string,而是使用类似的东西

 + (NSArray *)arrayWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION; 

事情变得更容易了。

在这种情况下,不要使用vprintf风格的函数,而是使用一个循环遍历args ,假设id为你,并且像在任何循环中一样parsing它们。

 - (void)logMessage:(NSString *)format, ... { va_list args; va_start(args, format); id arg = nil; while ((arg = va_arg(args,id))) { /// Do your thing with arg here } va_end(args); } 

当然,最后一个例子假设va_args列表没有被终止。

注意:为了使这个工作,你可能必须包括<stdarg.h> ; 但是如果内存服务,这将被包含在NSLogv中,这意味着它通过“Foundation.h”,因此还有“AppKit.h”和“Cocoa.h”以及其他一些内容。 所以这应该开箱即用。

 - (void)methodWithFormat:(NSString*)format, ... { va_list args; va_start(args,format); //loop, get every next arg by calling va_arg(args,<type>) // eg NSString *arg=va_arg(args,NSString*) or int arg=(args,int) va_end(args); } 

如果你想将可变parameter passing给stringWithFormat:,请使用如下所示:

 NSString *s=[[[NSString alloc] initWithFormat:format arguments:args] autorelease]; 

这里要提到的一点是,这里的第一个NSString参数是格式化的,另一个是在variables参数中传递的。 对? 所以在进入for循环之前,你需要一个参数来处理。

 - (NSString *) append:(NSString *)list, ... { NSMutableString * res = [NSMutableString string]; [res appendString:list]; va_list args; va_start(args, list); id arg = nil; while(( arg = va_arg(args, id))){ [res appendString:arg]; } va_end(args); return res; } - (void) test_va_arg { NSString * t = [self append:@"a", @"b", @"c", nil]; STAssertEqualObjects(@"abc", t, @""); }