RawRepresentable

使用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 事件名在不想要出现的时候被代码补全功能强行弹出来.

你可能感兴趣的:(RawRepresentable)