debugging Swift:打印()与打印输入()与NSLog()

4xrmg8kj  于 2022-11-14  发布在  Swift
关注(0)|答案(6)|浏览(169)

printNSLogprintln之间有什么区别?我应该在什么时候使用它们?
例如,在Python中,如果我想打印一个字典,我只需要print myDict,但是现在我有两个其他的选项,我应该如何以及何时使用它们?

f5emj3cl

f5emj3cl1#

几个不同之处:

  1. printprintln的比较:
    调试应用程序时,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样式的格式字符串,例如:
NSLog("%0.4f", CGFloat.pi)

这将产生:
[28937:1751492]我的手机应用程序[28937:1751492]

  • iOS 14/macOS 11中的NSLog可以使用字符串插值。(同样,在iOS 14和macOS 11中,我们通常更喜欢Logger而不是NSLog。请参阅下一点。)

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

  • 从iOS 14/macOS 11开始,我们有Logger接口连接到“统一日志”系统。有关Logger的介绍,请参见WWDC 2020 Explore logging in Swift
  • 要使用Logger,必须导入os
import os
  • NSLog一样,统一日志记录也会将消息输出到Xcode调试控制台和设备控制台
  • 创建一个Logger和一个log消息给它:
let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "network")
logger.log("url = \(url)")

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

  • 您可以指定不同类型的记录消息,例如.info.debug.error.fault.critical.notice.trace等:
logger.error("web service did not respond \(error.localizedDescription)")

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

  • 默认情况下,日志中的非数字数据会被编辑。在您记录URL的示例中,如果应用程序是从设备本身调用的,而您是从macOS Console应用程序观看的,您会在macOS Console中看到以下内容:

网址=
如果您确信此邮件不会包含用户机密数据,并且您希望在macOS控制台中看到这些字符串,则必须执行以下操作:

logger.log("url = \(url, privacy: .public)")
  • 在iOS 14/macOS 11之前,iOS 10/macOS 10.12引入了os_log来实现“统一日志”。关于统一日志的一般介绍,请参见WWDC 2016视频Unified Logging and Activity Tracing
  • 导入os.log
import os.log
  • 您应该定义subsystemcategory
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)
  • 如果您想观察仪器的活动范围,也可以使用“兴趣点”日志:
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调试器changes the app lifecycle。因此,您经常会希望在物理设备上进行测试,从设备本身运行应用。不从Xcode的调试器启动应用程序。统一日志记录让您仍然可以从macOS Console应用程序查看iOS设备日志语句。

kupeojn6

kupeojn62#

如果您使用的是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:".")
yshpjwxd

yshpjwxd3#

此外,Swift 2有debugPrint()(和CustomDebugStringConvertible协议)!

不要忘记debugPrint(),它的工作原理与print()类似,但most suitable for debugging除外。
示例:

*字符串

  • print("Hello World!")变为Hello World
  • debugPrint("Hello World!")变为"Hello World"(引号!)
    *范围
  • print(1..<6)变为1..<6
  • debugPrint(1..<6)变为Range(1..<6)

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

jtjikinw

jtjikinw4#

为了补充Rob的答案,自iOS 10.0以来,苹果推出了全新的“统一日志记录”系统,该系统取代了现有的日志记录系统(包括ASL和Syslog、NSLog),并在性能上超越了现有的日志记录方法,这要归功于其日志数据压缩和延迟数据收集等新技术。
来自Apple:
统一的日志记录系统提供了一个单一、高效、高性能的API,用于在系统的所有级别上捕获消息。此统一的系统将日志数据集中存储在内存和磁盘上的数据存储中。
Apple强烈推荐使用os_log来记录各种消息,包括信息、调试和错误消息,因为与以前的日志系统相比,它的性能有了很大的提高,而且它的集中式数据收集允许开发人员方便地检查日志和活动。事实上,新系统的内存占用很可能很低,不会导致“观察者效应,”即如果插入一个日志记录命令,bug就会消失,从而干扰bug发生的时间。

您可以在详细信息here中了解更多信息。
总结一下:为方便起见,请使用print()进行个人调试(但在用户设备上部署时,消息不会被记录)。然后,尽可能多地使用统一日志记录(os_log)进行其他操作。

gg58donl

gg58donl5#

iOS记录器

  1. NSLog-添加 meta信息(如时间戳和标识符)并允许您输出1023个符号。还将消息打印到控制台。这是最慢的方法。由于其他应用程序可以访问日志文件,因此不安全
@import Foundation
NSLog("SomeString")
  1. print-将all字符串打印到Xcode。性能比以前的更好
@import Foundation
print("SomeString")
  1. println(仅适用于Swift v1),并在字符串末尾添加\n
  2. os_log(来自iOS v10)-打印32768个符号也打印到控制台。性能比以前更好
@import os.log
os_log("SomeIntro: %@", log: .default, type: .info, "someString")
  1. Logger(来自iOS v14)-打印32768个符号也打印到控制台。性能比以前更好
@import os
let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "someCategory")
logger.log("\(s)")
mzsu5hc0

mzsu5hc06#

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

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

使用对象到标准输出的镜像转储对象的内容。
Swift Standard Library Functions开始

相关问题