下面是我想做的一个例子:
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError)
{
let nm = NetworkModel()
nm.sendlog("file name :AppDelegate , line number : 288", info: " Failed to register: \(error)")
}
当前场景I完成了硬编码值line number
和file name
,但是有可能通过程序挑选line number
和file name
吗?
6条答案
按热度按时间jdgnovmf1#
示例
使用参数中的默认值,还可以创建函数
在Swift 2.1中
有关详细信息,请参阅文档
qlfbtfca2#
您可以使用
#function
、#file
、#line
下面是swift中log方法的实现:https://github.com/InderKumarRathore/SwiftLog
下面是代码片段
daolsyd03#
对于斯威夫特4和斯威夫特5:
cnh2zyt34#
示例日志代码(TL; DR)的
请注意,您可能需要重新编写此代码,以便在私有/公共访问级别上获得更大的灵活性-
os_log
和Logger
处理隐私级别的方式不同。这只是为了说明如果您没有在message
中添加os_log
隐私级别,如何使用API。Apple建议使用OS Logging,这也是我使用这种方法而不是
print
语句的原因。我添加这个答案是因为iOS 14中新的Logger
API也支持字符串插值。动机
我认为这里的答案解决了**〈iOS 14的问题,但它们可以进一步提高内存效率**,因为这个调试日志记录功能可能会在iOS 14+(新的
Logger
API)的所有代码库中使用。苹果建议使用操作系统日志记录,这就是为什么我使用这种方法而不是print
语句(尽管这些语句仍然有效)。这些都是 * 微小 * 的改进,但我认为它们能有所帮助,因为即使是微小的改进也会累积起来。事实上,Swift标准库在任何地方都使用了这些优化)!这些优化是Swift难以置信的内存效率的贡献因素,尽管Swift是一种高级语言(也是伟大API设计的一部分!)。(-:
因为这个函数很可能适合作为一个通用的(OS)日志服务的一部分,所以我还包括了注意事项我在应用程序内进行日志记录时所做的。我认为这些可以帮助你调试日志**(我回答这个问题是因为它可能是调试日志!)
改进
1.如果我知道
Int
将是正,并且不太可能发生任何边缘情况崩溃,我更喜欢在某些情况下使用UInt
。由于这个原因,我不在与使用Int
类型的Foundation
类接口时使用UInt
。这分配的内存较少而且我发现更具体也能帮助我更好地理解代码。1.我更喜欢使用
StaticString
,因为我知道字符串在编译时是已知的。StaticString
仅提供对String
内容的低级访问,并且是不可变的。因此,请仅在适当的地方使用它。即使是串联的字符串文本也不能用于初始化StaticString
。因为它的功能比String
受到更多限制,这意味着它是轻量级-仅需要一个地址指针和长度。使用StaticString
还通过操作系统级内存管理提供少量性能提升,因为它既不分配也不释放(不需要引用计数)。1.使用Apple推荐的
Logger
API进行日志记录优于打印语句,原因如下:性能、隐私和统一管理。它可以更好地调试已发布产品中的问题(操作系统日志提供更多上下文)。我建议你尽可能使用
StaticString
,比如函数名和文件名,行号和列号使用UInt
。现在只有Logger
iOS 14+ API才能做到这一点。(额外)记录注意事项
我是否应该进行大量日志记录?
我认为日志记录是一个平衡的行为。如果你有权限访问崩溃报告,大量的日志记录对调试问题非常有帮助。但是,你需要平衡隐私,编译的二进制文件的大小和压倒日志记录系统。
1.隐私:将
"\(message, privacy: .private)"
与"\(message, privacy: .public)"
与Logger
一起使用时,请对敏感信息进行密文处理,并且在使用NSLog
或print
语句时,请勿打印敏感信息。建议在用于调试目的时,将print
语句(用于生产)替换为操作系统日志。或者在日志记录服务中使用预处理器指令(#if DEBUG
),以便仅在Debug
方案上使用print
。2.编译后的二进制文件的大小:日志语句实际上是更多行代码。添加的代码越多,二进制文件就越大。这通常不是问题,只要你不记录所有的东西,因为只有大幅增加此指标才会影响二进制文件的大小。
3.日志系统不堪重负:如果你过多地记录日志,设备可能不得不丢弃一些日志以保持运行(由于操作系统的多任务处理,运行时的RAM或交换空间有限--对于旧设备来说更糟糕)。苹果通常在处理大量用户日志方面是可靠的,但在实践中很难做到。然而,如果你确实遇到了这种情况,一些更有用的日志事件可能会被推出窗口。
操作系统日志
最重要的是日志级别。默认情况下,在iOS上,日志级别为
.info
及以下的日志条目将在日志生成时被抑制,因此唯一真实的的负面影响是二进制大小。如果您以.log
进行日志记录(.default
for os_log)或更高,您需要小心不要记录太多。Apple的一般建议是,您查看每个更高级别的日志条目,以确保它们包含在调试时可能有用的信息。最后,确保设置子系统和类别。统一日志记录系统处理大量日志条目-带类别的子系统使您更容易关注特定问题。
如何选择类别和子系统?
这是一个相当固执己见的主题,所以我会把重点放在我在做决定时会想到什么上。YMMV:可能有更好的选择,如果有,请让我知道。
**1.按功能(特定于产品):**例如,如果你是一个购物应用,可以按
payment
、login
或其他应用流程来组织subsystem
。如果你还没有使用模块化代码库来组织功能(或共享代码的框架),那么我可以推荐this tutorial series。**2.通过技术:**我的意思是代码的领域,它是用于推送通知、深度链接、用户默认值(或持久性)逻辑吗?这可能对
category
参数有帮助。**3.按目标:**如果可以的话,我也喜欢使用当前
Bundle
的bundleIdentifier
。如果您有扩展目标(推送通知)、多个目标或不同的平台(如WatchOS、SiriKit扩展等),这会更有意义。您可以使用以下代码获得当前捆绑包:使用操作系统设备日志调试用户问题
请参阅here以获得详细的演练(
Access Device Console Logs
)。主要思想是将设备连接到您的Mac(或者使用Mac本身来运行Mac应用程序;)),打开Console.app
,运行应用程序并尝试重现崩溃。如果你一开始就设法做到了这一点,那么你可以将崩溃时间与日志相关联,以获得更多的上下文。还有其他减少伐木的原因吗?
如果你是一个苹果早期采用者,那么你知道如何错误的一些iOS测试可以;)。向Apple发布错误报告时,操作系统日志会包含在
sysdiagnose
文件中,因此您可以获得更快的周转时间,因为您的错误报告噪音更小。我是否应该使用第三方日志记录服务?
取决于您是否负担得起以及是否真的需要。我倾向于最小化我在代码中导入的第三方依赖项的数量(如果我能控制这一点的话)而本机(Apple)Logging API在我的大多数用例中运行良好,但优点是用户无法查看日志(即使他想这样做)。请注意,如果您应用**
.private
日志级别,所以我通常不使用第三方服务(YMMV)。使用网络日志的一个潜在原因是,只要您信任第三方供应商防止数据泄露,它可以更安全地防止逆向工程**(但它不太环保;)).niwlg2el5#
yftpprvb6#
在代码中的任意位置(在struct/var/closure/func...中)添加下一行:
它将打印下一行: