528

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

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

4

6 回答 6

884

几个区别:

  1. printprintln

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

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

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

  2. 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.

  3. 从 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)")
      
  4. 在 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。例如printLogger你这样做:

      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 设备日志语句。

于 2014-09-20T17:40:42.390 回答
85

如果您使用的是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:".")
于 2015-06-16T18:32:45.360 回答
64

此外,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任何类都可以通过协议自定义其调试字符串表示。

于 2015-12-04T02:57:28.063 回答
44

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

来自苹果

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

Apple 强烈建议使用os_logforward 来记录各种消息,包括信息、调试、错误消息,因为与以前的日志记录系统相比,它的性能大大提高,并且它的集中数据收集允许开发人员方便地进行日志和活动检查。事实上,新系统的占用空间可能非常小,以至于它不会导致“观察者效应”,即如果您插入日志命令,您的错误就会消失,从而干扰错误发生的时间。

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

您可以在此处详细了解此内容。

总结一下:print()为方便起见用于您的个人调试(但在用户设备上部署时不会记录该消息)。os_log然后,尽可能多地使用统一日志记录 ( ) 来处理其他所有事情。

于 2017-02-18T10:24:48.367 回答
7

iOS 记录器

  1. NSLog- 添加元信息(如时间戳和标识符)并允许您输出1023 个符号。还将消息打印到控制台。最慢的方法。不安全,因为其他应用程序可以访问日志文件

    @import Foundation
    NSLog("SomeString")
    
  2. print-将所有字符串打印到 Xcode。比以前有更好的性能

    @import Foundation
    print("SomeString")
    
  3. println(仅适用于 Swift v1)并\n在字符串末尾添加

  4. os_log(来自 iOS v10) - 打印32768 个符号也打印到控制台。比以前有更好的性能

    @import os.log
    os_log("SomeIntro: %@", log: .default, type: .info, "someString")
    
  5. Logger(来自 iOS v14) - 打印32768 个符号也打印到控制台。比以前有更好的性能

    @import os
    let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "someCategory")
    logger.log("\(s)")
    
于 2020-11-11T12:18:38.227 回答
6

还有另一种方法被称为dump()也可用于记录:

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

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

来自Swift 标准库函数

于 2017-01-26T16:50:02.320 回答