Skip to content

Instantly share code, notes, and snippets.

@Skorch
Created October 20, 2016 00:12
Show Gist options
  • Save Skorch/9a637632fb0e34eb819c0f282c22babe to your computer and use it in GitHub Desktop.
Save Skorch/9a637632fb0e34eb819c0f282c22babe to your computer and use it in GitHub Desktop.
A protocol based solution to capturing analytics in Swift 3
//
// AnalyticsNotificationSubscriber.swift
// DropShift
//
// Created by Drew Beaupre on 2016-10-03.
// Copyright © 2016 drew.beaupre. All rights reserved.
//
import Foundation
class AnalyticsNotificationManager: NSObject{
var eventSubscribers = [EventType: SubscribableEvent.Type]()
override init() {
super.init()
addEventSubscriber(subscriber: EventType.SurveyAnswer.self)
addEventSubscriber(subscriber: EventType.GameStarted.self)
addEventSubscriber(subscriber: EventType.GameEnded.self)
addEventSubscriber(subscriber: EventType.GameReset.self)
}
private func addEventSubscriber(subscriber: SubscribableEvent.Type){
eventSubscribers[subscriber.eventType] = subscriber
NotificationCenter.default.addObserver(self, selector: #selector(AnalyticsNotificationManager.eventNofication(notification:)) , name: subscriber.eventType.notificationName, object: nil)
}
func eventNofication(notification: Notification){
guard
let eventType = EventType(notificationName: notification.name),
let eventSubscriber = eventSubscribers[eventType],
let eventProperties = notification.userInfo
else{
return
}
eventSubscriber.handleEvent(eventType: eventType, eventProperties: eventProperties)
}
}
//
// EventType+GameStarted.swift
// DropShift
//
// Created by Drew Beaupre on 2016-10-03.
// Copyright © 2016 drew.beaupre. All rights reserved.
//
import Foundation
extension EventType{
struct GameStarted: PublishableEvent, SubscribableEvent{
//MARK PropertyNames
private enum FieldNames: String{
case opponentType
}
//MARK Properties
private(set) var opponentType: PlayerType
//MARK:- PublishableEvent
var eventProperties: [String: Any]? {
return [
FieldNames.opponentType.rawValue: opponentType.description
]
}
//MARK:- SubscribableEvent
static var eventType: EventType{
return .gameStarted
}
}
}
//
// EventType+SurveyAnswer.swift
// DropShift
//
// Created by Drew Beaupre on 2016-10-18.
// Copyright © 2016 drew.beaupre. All rights reserved.
//
import Foundation
extension EventType{
struct SurveyAnswer: PublishableEvent, SubscribableEvent{
//MARK PropertyNames
private enum FieldNames: String{
case question, answer
}
//MARK Properties
private(set) var questionText: String
private(set) var answerValue: String
//MARK:- PublishableEvent
var eventProperties: [String: Any]? {
return [
FieldNames.question.rawValue: questionText,
FieldNames.answer.rawValue: answerValue
]
}
//MARK:- SubscribableEvent
static var eventType: EventType{
return .surveyAnswer
}
}
}
//
// EventType.swift
// DropShift
//
// Created by Drew Beaupre on 2016-10-03.
// Copyright © 2016 drew.beaupre. All rights reserved.
//
import Foundation
enum EventType: String{
case gameStarted = "Game Started"
case gameEnded = "Game Ended"
case gameReset = "Game Reset"
case surveyAnswer = "Survey Answer"
init?(notificationName: Notification.Name){
self.init(rawValue: notificationName.rawValue)
}
}
extension EventType{
var notificationName: NSNotification.Name{
return NSNotification.Name(rawValue: self.rawValue)
}
}
extension EventType{
var segmentName: String{
return self.rawValue
}
var gameAnalyticsName: String{
return self.rawValue.lowercased().replacingOccurrences(of: " ", with: ":")
}
}
//
// PublishableEvent.swift
// DropShift
//
// Created by Drew Beaupre on 2016-10-03.
// Copyright © 2016 drew.beaupre. All rights reserved.
//
import Foundation
protocol PublishableEvent{
var eventType: EventType {get}
var eventProperties: [String: Any]? { get }
}
extension PublishableEvent{
func publish(){
let userInfo = self.eventProperties
NotificationCenter.default.post(name: eventType.notificationName, object: nil, userInfo: userInfo)
}
}
extension PublishableEvent where Self: SubscribableEvent{
var eventProperties: [String: Any]? {
return [String: Any]()
}
var eventType: EventType{
return Self.eventType
}
}
class GameViewController: UIViewController {
//...lots of other stuff....
func gameStarted(opponentType: PlayerType) {
//publish the analytics
EventType.GameStarted(opponentType: opponentPlayerType).publish()
}
}
//
// SubscribableEvent.swift
// DropShift
//
// Created by Drew Beaupre on 2016-10-03.
// Copyright © 2016 drew.beaupre. All rights reserved.
//
import Foundation
import Analytics
protocol SubscribableEvent{
static var eventType: EventType {get}
// static func handleEvent(event: eventType: EventType, eventProperties: [AnyHashable: Any]) -> Void
// static func event(fromNotification notification: Notification) -> PublishableEvent?
}
extension SubscribableEvent{
static func handleEvent(eventType: EventType, eventProperties: [AnyHashable: Any]) -> Void{
var segmentProperties = [String: Any]()
eventProperties.forEach{
print("EventProperty: \($0.key), \($0.value)")
guard let keyString = $0.key as? String else{
print("Could not convert \($0.key) to string.")
return
}
segmentProperties[keyString] = $0.value
}
SEGAnalytics.shared().track(eventType.segmentName, properties: segmentProperties)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment