小编典典

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

all

有什么区别print,我应该在什么时候使用它们?NSLog``println

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


阅读 79

收藏
2022-03-10

共1个答案

小编典典

几个区别:

  1. printprintln

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

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

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

  1. NSLog

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

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

    • NSLog在 iOS 10-13/macOS 10.12-10.x 中使用printf-style 格式字符串,例如

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

这将产生:

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

* `NSLog`从 iOS 14/macOS 11 开始可以使用字符串插值。(然后,在 iOS 14 和 macOS 11 中,我们通常更倾向于`Logger`.`NSLog`见下一点。)

如今,虽然NSLog仍然有效,但我们通常会使用“统一日志记录”(见下文)而不是NSLog.

  1. 从 iOS 14/macOS 11 开始,我们有了Logger“统一日志”系统的接口。有关 的介绍Logger,请参阅 WWDC 2020探索使用 Swift 登录

    • 要使用Logger,您必须导入os

          import os
      
    • NSLog,统一日志也会同时向 Xcode 调试控制台和设备控制台输出消息

    • 创建一个Loggerlog一个消息给它:

          let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "network")
      

      logger.log(“url = (url)”)

当您通过外部控制台应用程序观察应用程序时,您可以根据subsystem和进行过滤category。将调试消息与 (a)
其他子系统代表您的应用程序生成的消息或 (b) 来自其他类别或类型的消息区分开来是非常有用的。

* 您可以指定不同类型的日志消息,包括`.info`、`.debug`、`.error`、`.fault`、`.critical`、`.notice`、`.trace`等:

            logger.error("web service did not respond \(error.localizedDescription)")

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

* 默认情况下,非数字数据会在日志中进行编辑。在您记录 URL 的示例中,如果应用程序是从设备本身调用的,并且您正在从 macOS 控制台应用程序观看,您将在 macOS 控制台中看到以下内容:

网址 = <私人>

如果您确信此消息不会包含用户机密数据并且您希望在 macOS 控制台中查看字符串,则必须执行以下操作:

            os_log("url = \(url, privacy: .public)")
  1. 在 iOS 14/macOS 11 之前,iOS 10/macOS 10.12 引入 os_log了“统一日志”。有关统一日志记录的一般介绍,请参阅 WWDC 2016 视频统一日志记录和活动跟踪

    • 进口os.log

          import os.log
      
    • 您应该定义subsystemand category

          let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "network")
      

使用时os_log,您将使用 printf 样式的模式而不是字符串插值:

            os_log("url = %@", log: log, url.absoluteString)


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

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


* 使用时不能使用字符串插值`os_log`。例如`print`,`Logger`你这样做:

            logger.log("url = \(url)")

但是os_log,你必须这样做:

            os_log("url = %@", url.absoluteString)


* 强制执行相同的`os_log`数据隐私,但您在 printf 格式化程序中指定公共可见性(例如`%{public}@`,而不是`%@`)。例如,如果您想从外部设备查看它,您必须这样做:

            os_log("url = %{public}@", url.absoluteString)


* 如果您想观看 Instruments 的活动范围,还可以使用“兴趣点”日志:

            let pointsOfInterest = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: .pointsOfInterest)

并开始一个范围:

            os_signpost(.begin, log: pointsOfInterest, name: "Network request")

并以以下方式结束:

            os_signpost(.end, log: pointsOfInterest, name: "Network request")

有关更多信息,请参阅https://stackoverflow.com/a/39416673/1271826

最重要的是,print对于使用 Xcode
进行简单的日志记录已经足够了,但是统一的日志记录(无论是Logger还是os_log)实现了同样的事情,但提供了更强大的功能。

当调试必须在 Xcode 之外进行测试的 iOS 应用程序时,统一日志记录的力量就显露出来。例如,在测试后台 iOS 应用程序进程(如后台获取)时,连接到
Xcode调试器会更改应用程序生命周期。因此,您经常需要在物理设备上进行测试,从设备本身运行应用程序,而不是从Xcode 的调试器启动应用程序。统一日志记录让您仍然可以从 macOS 控制台应用程序查看您的 iOS 设备日志语句。

2022-03-10