这周我的 App 的 0.9 版本已经审核通过了,我也在今天提交了 1.0 版本上去,目前为止看起来一切还是蛮顺利的。
由于 0.9 版本只是试水版本,1.0 才是正式版本,这个版本我做了一些专门为「Release」的一些改动,其中一点就是关于错误报告还有 Logging 的处理。简单的说,在开发过程中,我们可以用 NSLog 肆无忌惮地向终端输出各种信息,但是正式版本可不能这样了,不然用户手机的 Console 会被你的 Log 塞满,不仅影响性能,可能还会暴露不必要的一些开发信息。
那么,如何在 Swift 项目里正确地设置 Logging 呢?以下我以 Crashlytics 为例,当然,用其他工具甚至不用第三方工具也是可以的。
在过去 Objective-C 项目里,针对 Development 环境和 Release 环境使用不同的方法进行 Logging 我们是通过 Preprocessor Macros 来进行的。比如 DEBUG 是作为一个默认的 Macro 加进去的:看下图,只要有 $(inherited) 这个在,DEBUG 这个 Macro 就会存在项目的 Development 模式。
那么在 Swift 项目里面我们如何去区分 Debug 和 Release 模式呢?自然也有类似的方式。
实际上,Swift 语言也支持类似于 C 语言一样的 Macro,常用的那些基本能满足我们的使用需求。使在 Swift 项目里也和 Objective-C 一样使用 DEBUG 来区分 Debug 和 Release,我们只需要到 Target 的 Build Settings 里面,找到 Swift Compiler Custom Flags,在 Debug 处传入一个 -D DEBUG 即可。
这样如果你的项目混合了 Objective-C 和 Swift,Objective-C 代码依然会通过之前的 DEBUG 来做正确的分支编译,Swift 编译器也可以通过这个专门的 Custom Flags 来作分支编译。
定义好了这个,我们就可以做正确的 Logging 处理了。
在 AppDelegate.swift (或其他),我做了如下的定义:
import Crashlytics func NSLog(format: String, args: CVarArgType...) { #if DEBUG CLSNSLogv(format, getVaList([])) #else CLSLogv(format, getVaList([])) #endif }
主要说明:
于是我在 Swift 代码里重写了 NSLog 这个方法,使其根据不同的编译环境使用不同的 Crashlytics 方法,达到了我预期的效果。
这里还有一点可以改进或讨论的余地,由于 Swift 把 String 的使用变得很方便,我从环境变量构建一个字串再也不用像 Objective-C 那样:
NSLog(@"Hello, this is %@, I'm %d", name, age")
而是直接使用灵巧的 Swift 方式:
NSLog("Hello, this is /(name), I'm /(age)")
因而我用不着 args 部分,只通过 getVaList([]) 传一个空的参数列表进去即可。在实际的使用过程中,这个新包装的 NSLog 也永远也不需要去用到参数列表部分,直接用 Swift 的方式即可。
根据上图,由于我当前是 DEBUG 环境,Xcode 直接高亮了 #if DEBUG 那一块,方便我识别。这样,开发环境中我就可以在终端里看到 Log 输出,而在正式发布的时候它们就不会输出来。我可以像以前一样在项目的其他地方继续用 NSLog,所更改的地方也就是这么一个设置+短短的几行就完成了。
除了因为混合 Objective-C 和 Swift 环境的情况下,我们需要分别设置和确认 Macro/Flag 有没有被设置这点琐碎外,其他我用的还是蛮愉快的。
最后希望正式版早日审核通过 :)