打印一个NSString

33

在Objective-C中,打印NSString的正确方式是什么?很多例子使用NSLog(),但根据文档:

NSLog是FoundationKit中用于将调试语句打印到控制台的函数。 ... NSLog基本上像这样工作: fprintf(stderr, format_string, args ...);

对我来说有点像Win32/C ++中的_TRACE宏。我不想打印到stderr,我想打印到stdout。有人建议使用printf()如下:

printf("%s", [str cStringUsingEncoding:NSUTF8StringEncoding]);

但这看起来像是多余的间接层,用来打印NSString,并且它不太像解决方案。

6个回答

29

在Cocoa中,向stdout输出内容实际上是一件相当罕见的事情,因为几乎所有的项目都是GUI型的。只有少数项目被构建为命令行工具或者需要处理stdout

然而,Foundation提供了写入stdout的手段。具体来说,NSFileHandle有一个方法fileHandleWithStandardOutput,它可以给你一个文件句柄,可以写入stdout

从那里开始,就是将NSString转换为NSData并将其写入的问题。

虽然步骤相对较多,但可以很容易地封装成一个可重用的函数:

void MyLog(NSString *format, ...) {
    va_list args;
    va_start(args, format);
    NSString *formattedString = [[NSString alloc] initWithFormat: format
                                                  arguments: args];
    va_end(args);
    [[NSFileHandle fileHandleWithStandardOutput]
        writeData: [formattedString dataUsingEncoding: NSNEXTSTEPStringEncoding]];
    [formattedString release];
}

4
NSNEXTSTEPStringEncoding是指NeXTSTEP操作系统所使用的字符串编码格式。 - Hakanai
抱歉打扰,但是如何在日志行之间插入'\n'?不想在这样的日志记录中浪费太多的循环。 - Motti Shneor
啊,也许你知道为什么使用 prinff("%s\n", [formattedString UTFString]) 这种方法会在我的打印行中输出各种垃圾? - Motti Shneor
可能是因为你正在将Unicode字符串传递给期望ASCII字符串的某个地方。如果你正在使用printf,只需打印一个换行符。性能已经被破坏了。 - bbum

26

这就是解决方案。

由于printf是纯C函数,无法识别Objective-C对象。 (NSLog的格式化程序与printf的不同.) 因此,在格式化之前,您必须将其转换为C字符串。

另外,您可以使用[str UTF8String]而不是[str cStringUsingEncoding:NSUTF8StringEncoding]


7
我理解printf是一个纯C函数,但我觉得很奇怪,为了打印NSString,你必须使用它,而不是Core Foundation有一个文本IO库。 - ta.speot.is

10

C字符串(UTF8String)是指向字符串对象内部结构的指针。

NSString *str = @"Hello, World.";
printf("%s\n", [str UTF8String]);

4
我认为这些内容能够满足您的需求:

我认为这些内容能够满足您的需求:

// print to stdout
static void NSPrint(NSString *format, ...) {
    va_list args;
    va_start(args, format);

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

    va_end(args);

    fprintf(stdout, "%s\n", [string UTF8String]);

#if !__has_feature(objc_arc)
    [string release];
#endif
}

// print to stderr
static void NSPrintErr(NSString *format, ...) {
    va_list args;
    va_start(args, format);

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

    va_end(args);

    fprintf(stderr, "%s\n", [string UTF8String]);

#if !__has_feature(objc_arc)
    [string release];
#endif
}

3

您应该使用自定义文件处理程序或自己编写宏。

提示:当NSLog打印对象时,它使用对象的debugDescription方法。 您可以为自定义NSObject子类覆盖此方法,以将自定义debugInfo打印到标准输出。


太棒了!我绝对不知道那个。 - Steven Hepting

0

我只是做:

define NSPrintf(...)   printf( "%s", [[NSString stringWithFormat: __VA_ARGS__] UTF8String] )

然后我可以这样使用它:

NSPrintf( @"Sorry %@, I can't do that\n", name );

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接