☂️ Umbrella(雨伞)

Swift CocoaPods CI Codecov

Swift 的分析抽象层。灵感来源于 Moya

目录

为什么使用?

有很多移动应用分析工具,例如 Firebase、Google Analytics、Fabric Answers、Flurry、Mixpanel 等。你可能会在你的应用中使用其中的一个或多个。 但是这些 SDK 大部分都有一些问题:如果你使用多个分析工具,你的代码会变得混乱。 并且这些 SDK 将事件名称作为字符串,参数作为字典,Swift 编译器不能保证其正确性。 这意味着如果你更改了事件定义,你需要手动查找所有相关的代码。 这有导致人为错误的机会。 Umbrella 使用 Swift 枚举和关联值来解决这些问题。

特性

概览

之前 🤢

FIRAnalytics.logEvent(withName: kFIREventEcommercePurchase, parameters: [
  kFIRParameterCurrency: "USD" as NSObject,
  kFIRParameterValue: 9.99 as NSNumber,
  kFIRParameterTransactionID: "20170709123456" as NSObject,
])
Flurry.logEvent("purchase", withParameters: [
  "Currency": "USD",
  "Price": 9.99,
  "Transaction ID": "20170709123456"
])
MyCustomAnalytics.logEvent("purchase", withParameters: [
  "currency": "USD",
  "price": 9.99,
  "transaction_id": "20170709123456"
])

之后 😊

let analytics = Analytics<MyAppEvent>()
analytics.register(provider: FirebaseProvider())
analytics.register(provider: FlurryProvider())
analytics.register(provider: MyCustomProvider())
analytics.log(.purchase(currency: "USD", price: 9.99, transactionID: "20170709123456"))

开始使用

定义事件

首先,你应该在一个枚举中定义你所有的事件。 假设我们有三个具有相关参数的事件。

enum MyAppEvent {
  case signup(username: String)
  case viewContent(productID: Int)
  case purchase(productID: Int, price: Float)
}

然后使枚举遵循 EventType 协议。它需要两个函数:name(for:)parameters(for:)

extension MyAppEvent: EventType {
  /// An event name to be logged
  func name(for provider: ProviderType) -> String? {
    switch self {
    case .signup: return "signup"
    case .viewContent: return "view_content"
    case .purchase: return "purchase"
    }
  }

  /// Parameters to be logged
  func parameters(for provider: ProviderType) -> [String: Any]? {
    switch self {
    case let .signup(username):
      return ["username": username]
    case let .viewContent(productID):
      return ["product_id": productID]
    case let .purchase(productID, price):
      return ["product_id": productID, "price": price]
    }
  }
}

你甚至可以为不同的 provider 提供不同的事件名称和参数。

使用分析

你可以在任何地方定义一个 Analytics 实例,但建议在全局范围内定义。

let analytics = Analytics<MyAppEvent>()

然后你应该注册 providers。Provider 是一个实际分析服务的包装器,例如 Firebase 和 Fabric Answers。 建议在 application(_:didFinishLaunchingWithOptions:) 中注册 providers。

analytics.register(provider: AnswersProvider())
analytics.register(provider: FirebaseProvider())
analytics.register(provider: FlurryProvider())
analytics.register(provider: MyAwesomeProvider())

如果你完成了这些步骤,你现在可以记录事件了 🎉

analytics.log(.signup(username: "devxoul"))

内置 Providers

有几个内置的 providers。

如果没有你要找的 provider,你可以 创建一个 issue 或者 创建自定义 providers。 也欢迎为缺失的服务创建 pull request 🎉

创建自定义 Providers

如果没有你正在使用的服务的内置 provider,你也可以创建自己的。 创建 provider 很容易:只需创建一个类并遵循 ProviderType 协议。

final class MyAwesomeProvider: ProviderType {
  func log(_ eventName: String, parameters: [String: Any]?) {
    AwesomeAnalytics.logEvent(withName: eventName, parameters: parameters)
  }
}

安装

Umbrella 目前仅支持 CocoaPods

pod 'Umbrella'
pod 'Umbrella/Firebase' # using with built-in FirebaseProvider
pod 'Umbrella/...'

贡献

欢迎任何讨论和 pull request 💖

生成 Xcode Workspace

$ make project

这将自动生成 Umbrella.xcworkspace 并执行 pod install

创建新 Provider

例如,假设我们将为分析服务 'Raincoat' 创建一个新的 provider。

  1. Package.swift 中添加一个库和一个目标定义。

      let package = Package(
        name: "Umbrella",
        products: [
          .library(name: "Umbrella", targets: ["Umbrella"]),
          .library(name: "UmbrellaFirebase", targets: ["UmbrellaFirebase"]),
          .library(name: "UmbrellaMixpanel", targets: ["UmbrellaMixpanel"]),
    +     .library(name: "UmbrellaRaincoat", targets: ["UmbrellaRaincoat"]),
        ],
        targets: [
          .target(name: "Umbrella"),
          .target(name: "UmbrellaFirebase", dependencies: ["Umbrella"]),
          .target(name: "UmbrellaMixpanel", dependencies: ["Umbrella"]),
    +     .target(name: "UmbrellaRaincoat", dependencies: ["Umbrella"]),
          .testTarget(name: "UmbrellaTests", dependencies: ["Umbrella"]),
          .testTarget(name: "UmbrellaFirebaseTests", dependencies: ["UmbrellaFirebase"]),
          .testTarget(name: "UmbrellaMixpanelTests", dependencies: ["UmbrellaMixpanel"]),
    +     .testTarget(name: "UmbrellaRaincoat", dependencies: ["UmbrellaRaincoat"]),
        ]
      )
  2. 添加一个源文件和一个测试文件。

      ...
      ├── Sources
      │   ├── UmbrellaFirebase
      │   │   └── FirebaseProvider.swift
      │   ├── UmbrellaMixpanel
      │   │   └── MixpanelProvider.swift
    + │   ├── UmbrellaRaincoat
    + │   │   └── RaincoatProvider.swift
      |   ...
      ├── Tests
      │   ├── UmbrellaFirebaseTests
      │   │   └── FirebaseProviderTests.swift
      │   ├── UmbrellaMixpanelTests
      │   │   └── MixpanelProviderTests.swift
    + │   ├── UmbrellaRaincoatTests
    + │   │   └── RaincoatProviderTests.swift
      ... ...
  3. Podfile 中添加一个 CocoaPods 依赖项。

     target 'UmbrellaFirebaseTests' do
       platform :ios, '8.0'
       pod 'Firebase/Analytics'
     end
    
     target 'UmbrellaMixpanelTests' do
       platform :ios, '8.0'
       pod 'Mixpanel'
     end
    
    + target 'UmbrellaRaincoatTests' do
    +   platform :ios, '8.0'
    +   pod 'Raincoat'
    + end
  4. Umbrella.podspec 中添加一个 CocoaPods subspec。

      s.subspec "Firebase" do |ss|
        ss.source_files = "Sources/UmbrellaFirebase/*.swift"
        ss.dependency "Umbrella/Core"
      end
    
      s.subspec "Mixpanel" do |ss|
        ss.source_files = "Sources/UmbrellaMixpanel/*.swift"
        ss.dependency "Umbrella/Core"
      end
    
    + s.subspec "Raincoat" do |ss|
    +   ss.source_files = "Sources/UmbrellaRaincoat/*.swift"
    +   ss.dependency "Umbrella/Core"
    + end
  5. 创建一个 Xcode workspace 并运行测试。 不要忘记检查代码覆盖率以确保测试可以覆盖新的 provider。

    $ make project

许可协议

Umbrella 使用 MIT 许可证。 有关更多信息,请参见 LICENSE 文件。