有什么区别print
,我应该在什么时候使用它们?NSLog
println
例如,在 Python 中,如果我想打印字典,我会print myDict
选择 ,但现在我有 2 个其他选项。我应该如何以及何时使用每个?
几个区别:
print
与println
:
该print
函数在调试应用程序时在 Xcode 控制台中打印消息。
这println
是一个在 Swift 2 中被删除并且不再使用的变体。如果您看到正在使用的旧代码println
,您现在可以安全地将其替换为print
.
回到 Swift 1.x 中,print
没有在打印字符串的末尾添加换行符,而println
这样做了。但是现在,print
总是在字符串末尾添加换行符,如果您不希望它这样做,请terminator
提供""
.
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
.
从 iOS 14/macOS 11 开始,我们拥有Logger
“统一日志”系统的接口。有关 的介绍Logger
,请参阅 WWDC 2020探索使用 Swift 登录。
要使用Logger
,您必须导入os
:
import os
像NSLog
,统一日志也会同时向 Xcode 调试控制台和设备控制台输出消息
创建一个Logger
和log
一个消息给它:
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)")
在 iOS 14/macOS 11 之前,iOS 10/macOS 10.12 引入 os_log
了“统一日志记录”。有关统一日志记录的一般介绍,请参阅 WWDC 2016 视频统一日志记录和活动跟踪。
进口os.log
:
import os.log
您应该定义subsystem
and 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 设备日志语句。
如果您使用的是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:".")
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
任何类都可以通过协议自定义其调试字符串表示。
为了补充 Rob 的答案,自 iOS 10.0 以来,Apple 引入了一个全新的“统一日志记录”系统,该系统取代了现有的日志记录系统(包括 ASL 和 Syslog、NSLog),并且在性能上也超越了现有的日志记录方法,这要归功于其新技术,包括日志数据压缩和延迟数据收集。
来自苹果:
统一的日志系统提供了一个单一的、高效的、高性能的 API,用于捕获跨系统所有级别的消息。这个统一的系统将日志数据集中存储在内存和磁盘上的数据存储中。
Apple 强烈建议使用os_log
forward 来记录各种消息,包括信息、调试、错误消息,因为与以前的日志记录系统相比,它的性能大大提高,并且它的集中数据收集允许开发人员方便地进行日志和活动检查。事实上,新系统的占用空间可能非常小,以至于它不会导致“观察者效应”,即如果您插入日志命令,您的错误就会消失,从而干扰错误发生的时间。
您可以在此处详细了解此内容。
总结一下:print()
为方便起见用于您的个人调试(但在用户设备上部署时不会记录该消息)。os_log
然后,尽可能多地使用统一日志记录 ( ) 来处理其他所有事情。
iOS 记录器
NSLog
- 添加元信息(如时间戳和标识符)并允许您输出1023 个符号。还将消息打印到控制台。最慢的方法。不安全,因为其他应用程序可以访问日志文件
@import Foundation
NSLog("SomeString")
print
-将所有字符串打印到 Xcode。比以前有更好的性能
@import Foundation
print("SomeString")
println
(仅适用于 Swift v1)并\n
在字符串末尾添加
os_log
(来自 iOS v10) - 打印32768 个符号也打印到控制台。比以前有更好的性能
@import os.log
os_log("SomeIntro: %@", log: .default, type: .info, "someString")
Logger
(来自 iOS v14) - 打印32768 个符号也打印到控制台。比以前有更好的性能
@import os
let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "someCategory")
logger.log("\(s)")
还有另一种方法被称为dump()
也可用于记录:
func dump<T>(T, name: String?, indent: Int, maxDepth: Int, maxItems: Int)
使用其镜像将对象的内容转储到标准输出。