斯威夫特:print()vs println()vs NSLog()


449

什么之间的区别printNSLog以及println何时该使用的呢?

例如,在Python中,如果我想打印字典,我只是print myDict,但是现在有2个其他选项。我应该如何以及何时使用它们?



2
NSLog和打印NSDictionary不会给我任何有用的信息吗?
用户

从iOS 10.0开始,建议使用os_log。请在下面查看我的答案。
HuaTham

除了查看上的Swift文档外,还请os_log尝试查看Objective-C页面的完整文档。它更加完整
亲爱的

Answers:


756

一些区别:

  1. printvs println

    print调试应用程序时,该函数在Xcode控制台中打印消息。

    println是Swift 2中已删除且不再使用的变体。如果看到正在使用的旧代码,则println现在可以安全地将其替换为print

    回到Swift 1.x,print没有在打印字符串的末尾添加换行符,而是添加了换行符println。但如今,请print始终在字符串的末尾添加换行符,如果您不希望这样做,请提供terminator参数""

  2. NSLog

    • NSLog 更慢

    • NSLog在输出中添加时间戳和标识符,而print不会;

    • NSLog语句同时出现在设备的控制台和调试器的控制台中,而print仅出现在调试器的控制台中。

    • NSLog使用printf-style格式的字符串,例如

      NSLog("%0.4f", CGFloat.pi)

      会产生:

      2017-06-09 11:57:55.642328-0700 MyApp [28937:1751492] 3.1416

  3. 对于有效的iOS 10 / macOS 10.12,还有第三种选择,os_log即“统一日志记录”系统的一部分(请参阅WWDC 2016视频统一日志记录和活动跟踪)。

    • 您必须先导入,os.log然后才能使用os_log函数:

      import os.log
    • 像一样NSLogos_log也会将消息输出到Xcode调试控制台和设备控制台。

    • 现在,您可以控制控制台应用程序中可用的“子系统”和“类别”字段。例如:

      let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "network")
      os_log("url = %@", log: log, url.absoluteString)
      

      通过外部控制台应用程序观察该应用程序时,您不仅可以将这些列添加到主视图,还可以基于这些列进行过滤。想要将调试消息与(a)其他子系统代表您的应用程序生成的消息区分开来时,这非常有用。或(b)来自其他类别或类型的消息。

    • 您可以指定不同类型的日志信息,无论是.info.debug.error.fault(或.default):

      os_log("web service did not respond", type: .error)

      因此,如果使用外部控制台应用程序,则可以选择仅查看某些类别的消息(例如,如果在控制台的“操作”菜单上选择“包括调试消息”,则仅显示调试消息)。这些设置还规定了有关是否将内容记录到磁盘的许多细微问题的详细信息。有关更多详细信息,请参阅WWDC视频。

    • 使用时不能使用字符串插值os_log。例如,您不能执行以下操作:

      os_log("foo \(url.absoluteString)")

      您将必须执行以下操作:

      os_log("url = %@", url.absoluteString)
    • 上述限制的原因之一是为了支持数据隐私。默认情况下,原始数据类型(例如,数字)是公共的,而对象(例如,字符串)在默认情况下是私有的。在记录URL的上一个示例中,如果从设备本身调用了该应用程序,并且正在从Mac的Console应用程序观看,则将看到:

      url = <私人>

      如果要从外部设备查看它,则必须执行以下操作:

      os_log("url = %{public}@", url.absoluteString)
    • 注意,NSLog现在在幕后使用统一通知系统,但有以下警告:

      • 您无法控制子系统,类别或日志类型;

      • 它不支持隐私设置。

底线print足以完成简单的任务,但NSLog很有用,因为它包含了您的时间戳信息。

的功率os_log调试具有的Xcode以外的地方进行测试iOS应用程序,当进入鲜明的救济。例如,当测试后台iOS应用程序进程(例如后台获取)时,连接到Xcode调试器会更改应用程序生命周期。因此,您经常需要在物理设备上进行测试,而不是从Xcode的调试器启动应用程序,而是从设备本身运行应用程序。统一日志记录使您仍然可以os_log从macOS控制台应用程序观看iOS设备语句。


37
不错的总结!要添加更多内容:您可以将NSString传递给println,但不能传递给NSLog。您可以为NSLog添加参数,但不能为println添加参数;Swift样式字符串插值有时会因NSLog而崩溃,但不会导致println崩溃。
鲍磊

2
关于Swift编译器优化和使用print()medium.com/ios-os-x-development/…
Carl

@Rob如果我使用print,那么它是否出现在调试器控制台中?还是我们应该使用debugPrint?

1
如果使用print,它将显示在Xcode的调试区域中,就像debugPrint。唯一的区别是print最终导致description了对象的调用方法和debugPrint调用debugDescription,这可能比更加冗长description
罗布

@Honey,此评论线程被标记为过长,因此我只想提醒您,这些评论不适用于扩展讨论或调试会话。如果您有什么问题可以问到适合于Stack Overflow格式的问题,以问题的形式提出,以便每个人都可以从其答案中受益。如果这不是一个问题,那么您将需要进行讨论以聊天。保留评论仅用于要求澄清或快速观察。
科迪·格雷

79

如果您使用的是Swift 2,现在只能使用print()将某些内容写入输出中。

Apple已将println()print()函数合并为一个。

更新至iOS 9

默认情况下,该函数通过添加换行符来终止其打印的行。

print("Hello Swift")

终结者

要打印后没有换行符的值,请传递一个空字符串作为终止符

print("Hello Swift", terminator: "")

分隔器

您现在可以使用分隔符来连接多个项目

print("Hello", "Swift", 2, separator:" ")

或者您可以通过这种方式组合使用

print("Hello", "Swift", 2, separator:" ", terminator:".")

5
appendNewline的默认值为true
Adam

1
在iOS(9.0)中,您需要使用terminator : "",例如print("...", terminator: "")
Khotu Nam

您第一句话中的陈述不正确。的NSLog()仍然有效,即使在最新的斯威夫特2.X
塞巴斯蒂安

62

而且,Swift 2具有debugPrint()(和CustomDebugStringConvertible协议)!

不要忘了debugPrint()其工作方式print(),但最适合的调试

例子:

  • 弦乐
    • print("Hello World!") 变成 Hello World
    • debugPrint("Hello World!")成为"Hello World"(行情!)
  • 范围
    • print(1..<6) 变成 1..<6
    • debugPrint(1..<6) 变成 Range(1..<6)

任何类都可以通过CustomDebugStringConvertible协议自定义其调试字符串表示形式。


2
DebugPrintableprotocol已重命名为CustomDebugStringConvertibleprotocol
富兰克林于

谢谢,富兰克林!
Valentin Shergin '16

如此迅速的descriptiondebugDescription为Python的strrepr
BallpointBen,

是的,我想是这样。
Valentin Shergin '17

39

为了补充Rob的答案,自iOS 10.0起,Apple引入了一种全新的“统一日志记录”系统,该系统取代了现有的日志记录系统(包括ASL和Syslog,NSLog),并且由于其新技术,其性能也超过了现有的日志记录方法。日志数据压缩和延迟数据收集。

苹果

统一日志记录系统提供了一个单一,高效,高性能的API,用于捕获系统所有级别的消息。该统一系统集中了日志数据在内存中和磁盘上的数据存储中的存储。

Apple强烈建议使用os_log向前记录各种消息,包括信息,调试,错误消息,因为与以前的记录系统相比,它的性能大大提高,并且其集中的数据收集功能为开发人员提供了方便的日志和活动检查。实际上,新系统的占用空间可能很小,因此如果您插入日志记录命令,不会导致臭虫消失的“观察者效应”,从而干扰了臭虫发生的时间。

活动跟踪的性能,现在已成为新的统一日志系统的一部分

您可以在此处详细了解更多信息。

总结一下:print()为方便您的个人调试(但是在用户设备上部署时不会记录该消息)。然后,os_log对于其他所有内容,请尽可能使用统一日志记录()。


5

还有一种称为的方法dump(),也可以用于记录日志:

func dump<T>(T, name: String?, indent: Int, maxDepth: Int, maxItems: Int)

使用其镜像将对象的内容转储到标准输出。

Swift标准库函数

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.