使用RawRepresentabloe可以在自定义类型和相应的rawValue之间来回切换
比如我们使用一个结构体来管理埋点事件
struct EventID: RawRepresentable {
}
然后根据提示补全代码
struct EventID: RawRepresentable {
typealias RawValue = String
var rawValue: String
init?(rawValue: String) {
}
}
从这就更容易看出其原理, 实际上内部的 rawValue 属性就是我们需要使用的 String 类型的事件名, 初始化方法传入该 String 对其赋值即可, 返回 EventID 类型的结构体
这里发现初始化方法返回的是一个 Optional 类型, 这样使用起来还需要解包, 不太方便, 可以看到 Notification.Name 的初始化方法返回并不是 Optional, 因为定义都是非常确定的事件名(通知名), 而且 init 方法中也不会产生异常, 所以此处没什么必要使用 Optional, 去掉 ? 即可
struct EventID: RawRepresentable {
typealias RawValue = String
var rawValue: String
init(rawValue: String) {
self.rawValue = rawValue
}
}
那么我们上报代码如下:
class EventReporter {
static let shared = EventReporter()
func reportEvent(_ eventId: EventID, withParams params: [String:Any]? = nil) {
let event = eventId.rawValue
// 埋点逻辑
}
}
最后, 定义一个埋点事件看看吧~, 推荐写到 extension 中易于维护.
extension EventID {
static let LoginPageExposure = EventID(rawValue: "login_page_exposure")
}
那么使用的时候
1. EventReporter.shared.reportEvent(.LoginPageExposure)
当我们打出 . 的时候, 代码补全就已经将 LoginPageExposure 提示给我们了.
总结
使用这种方式优化代码, 不仅可以让代码意图容易理解, 使用也更加简单不会出错. 而且也不会使得 LoginPageExposure 事件名在不想要出现的时候被代码补全功能强行弹出来.