print
、NSLog
和println
之间有什么区别?我应该在什么时候使用它们?
例如,在Python中,如果我想打印一本字典,我只有print myDict
本,但现在我有两个其他选项.我应该如何以及何时使用它们?
print
、NSLog
和println
之间有什么区别?我应该在什么时候使用它们?
例如,在Python中,如果我想打印一本字典,我只有print myDict
本,但现在我有两个其他选项.我应该如何以及何时使用它们?
有几点不同:
print
对println
:
调试应用程序时,print
函数在Xcode控制台中打印消息.
println
是Swift 2中删除的版本,不再使用.如果看到使用println
的旧代码,现在可以安全地将其替换为print
.
回到Swift 一号.x、 print
没有在打印字符串的末尾添加换行符,而println
没有.但是现在,print
总是在字符串的末尾添加换行符,如果不希望它这样做,请提供terminator
参数""
.
NSLog
:
NSLog
向输出添加时间戳和标识符,而print
不会;
NSLog
条语句同时出现在设备控制台和调试器控制台中,而print
条语句只出现在调试器控制台中.
NSLog
在iOS 10-13/macOS 10.12-10中.x使用printf
样式格式字符串,例如.
NSLog("%0.4f", CGFloat.pi)
这将产生:
2017-06-09 11:57:55.642328-0700 MyApp[28937:1751492]3.1416
来自iOS 14/macOS 11的NSLog
可以使用字符串插值.(同样,在iOS 14和macOS 11中,我们通常倾向于Logger
而不是NSLog
.请看下一点.)
如今,虽然NSLog
仍然有效,但我们通常使用"统一日志(log)"(见下文)而不是NSLog
.
有效的iOS 14/macOS 11,我们有Logger
个与"统一日志(log)"系统的接口.有关Logger
的介绍,请参见WWDC 2020 Explore logging in Swift.
要使用Logger
,必须导入os
:
import os
与NSLog
一样,统一日志(log)也将向Xcode调试控制台和设备控制台输出消息
创建一个Logger
并向其发送消息:
let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "network")
logger.log("url = \(url)")
通过外部控制台应用程序观察应用程序时,可以根据subsystem
和category
进行过滤.区分调试消息与(a)其他子系统代表应用程序生成的消息,或(b)其他类别或类型的消息非常有用.
您可以指定不同类型的日志(log)消息,如.info
、.debug
、.error
、.fault
、.critical
、.notice
、.trace
等:
logger.error("web service did not respond \(error.localizedDescription)")
因此,如果使用外部控制台应用程序,您可以 Select 仅查看特定类别的消息(例如,如果在控制台"操作"菜单上 Select "包括调试消息",则仅显示调试消息).这些设置还决定了许多微妙的问题,比如是否将内容记录到磁盘.有关更多详细信息,请参阅WWDC视频.
默认情况下,非数字数据会在日志(log)中进行编辑.在您记录URL的示例中,如果应用程序是从设备本身调用的,并且您是从macOS控制台应用程序观看的,您将在macOS控制台中看到以下内容:
url=<;私有>;
如果您确信此消息不会包含用户机密数据,并且希望在macOS控制台中看到字符串,则必须执行以下操作:
os_log("url = \(url, privacy: .public)")
在iOS 14/macOS 11之前,iOS 10/macOS 10.12引入了用于"统一日志(log)"的os_log
.有关统一日志(log)的一般介绍,请参阅WWDC 2016 video Unified Logging and Activity Tracing.
进口os.log
:
import os.log
您应该定义subsystem
和category
:
let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "network")
使用os_log
时,您将使用printf样式的图案,而不是字符串插值:
os_log("url = %@", log: log, url.absoluteString)
您可以指定不同类型的日志(log)消息,.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)
如果您想从仪器上观看各种活动,也可以使用"兴趣点"日志(log):
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的简单日志(log)记录来说已经足够了,但是统一日志(log)记录(不管是Logger
还是os_log
)实现了同样的功能,但提供了更大的功能.
当调试必须在Xcode之外测试的iOS应用程序时,统一日志(log)记录的威力得到了极大的释放.例如,在测试后台iOS应用程序进程(如后台获取)时,连接到Xcode调试器changes the app lifecycle.因此,您经常需要在物理设备上进行测试,从设备本身运行应用程序,而不是从Xcode的调试器启动应用程序.通过统一日志(log)记录,您仍然可以在macOS控制台应用程序中查看iOS设备日志(log)语句.