From 833d074b71fcd11d11a68a348ba11673786078d1 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto <5731772+marandaneto@users.noreply.github.com> Date: Mon, 23 Oct 2023 16:29:50 +0200 Subject: [PATCH] Addressed a few comments from the code review (#77) --- CONTRIBUTING.md | 14 +++ LICENSE | 8 +- Makefile | 8 +- PostHog.xcodeproj/project.pbxproj | 18 ++-- PostHog/{ => Models}/PostHogEvent.swift | 0 PostHog/PostHogExtensions.swift | 2 - PostHog/Utils/MethodSwizzler.swift | 118 ------------------------ PostHog/Utils/Swizzle.swift | 20 ---- PostHogExample/AppDelegate.swift | 13 +++ 9 files changed, 45 insertions(+), 156 deletions(-) create mode 100644 CONTRIBUTING.md rename PostHog/{ => Models}/PostHogEvent.swift (100%) delete mode 100644 PostHog/Utils/MethodSwizzler.swift delete mode 100644 PostHog/Utils/Swizzle.swift diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000000..688c9ffa88 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,14 @@ +Contributing +============ + +If you would like to contribute code to `posthog-ios` you can do so through +GitHub by forking the repository and opening a pull request against `master`. + +Run `make bootstrap` to install all dependencies. + +When submitting code, please make every effort to follow existing conventions +and style in order to keep the code as readable as possible. Please also make +sure your code compiles by `make build`. In addition please consider adding +unit tests covering your change, this will make your change much more likely to be accepted + +Above all, thank you for contributing! diff --git a/LICENSE b/LICENSE index 244538035e..7e799e3c4e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,10 +1,6 @@ -Copyright (c) 2020-2023 PostHog Inc. +MIT License -Portions of this software are licensed as follows: - -* All content that resides under the "ee/" directory of this repository, if that directory exists, is licensed under the license defined in "ee/LICENSE". -* All third party components incorporated into the PostHog Software are licensed under the original license provided by the owner of the applicable component. -* Content outside of the above mentioned directories or restrictions above is available under the "MIT Expat" license as defined below. +Copyright (c) [2023] [PostHog] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index b51209742e..a33074c474 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: build buildSdk buildExample format swiftLint swiftFormat test lint +.PHONY: build buildSdk buildExample format swiftLint swiftFormat test lint bootstrap build: buildSdk buildExample @@ -21,3 +21,9 @@ test: lint: swiftformat . --lint --swiftversion 5.3 && swiftlint + +# requires gem and brew +bootstrap: + gem install xcpretty + brew install swiftlint + brew install swiftformat diff --git a/PostHog.xcodeproj/project.pbxproj b/PostHog.xcodeproj/project.pbxproj index ff09f00720..117c689c46 100644 --- a/PostHog.xcodeproj/project.pbxproj +++ b/PostHog.xcodeproj/project.pbxproj @@ -9,9 +9,7 @@ /* Begin PBXBuildFile section */ 3A0F108329C47940002C0084 /* UIViewExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A0F108229C47940002C0084 /* UIViewExample.swift */; }; 3A0F108529C9ABB6002C0084 /* ReadWriteLock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A0F108429C9ABB6002C0084 /* ReadWriteLock.swift */; }; - 3A0F108729C9BD23002C0084 /* MethodSwizzler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A0F108629C9BD23002C0084 /* MethodSwizzler.swift */; }; 3A0F108929C9BD76002C0084 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A0F108829C9BD76002C0084 /* Errors.swift */; }; - 3A2BCF4A299E2BDA008BB5F3 /* Swizzle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2BCF49299E2BDA008BB5F3 /* Swizzle.swift */; }; 3A2BCF4C299E4E35008BB5F3 /* QueueTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2BCF4B299E4E35008BB5F3 /* QueueTest.swift */; }; 3A2BCF52299F7724008BB5F3 /* CodableUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A2BCF51299F7724008BB5F3 /* CodableUtils.swift */; }; 3A4F510D299A78E100B68D5E /* NSData+PHGGZIP.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AE3FB3829924CE100AFFC18 /* NSData+PHGGZIP.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -100,9 +98,7 @@ /* Begin PBXFileReference section */ 3A0F108229C47940002C0084 /* UIViewExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewExample.swift; sourceTree = ""; }; 3A0F108429C9ABB6002C0084 /* ReadWriteLock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadWriteLock.swift; sourceTree = ""; }; - 3A0F108629C9BD23002C0084 /* MethodSwizzler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MethodSwizzler.swift; sourceTree = ""; }; 3A0F108829C9BD76002C0084 /* Errors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; - 3A2BCF49299E2BDA008BB5F3 /* Swizzle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Swizzle.swift; sourceTree = ""; }; 3A2BCF4B299E4E35008BB5F3 /* QueueTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QueueTest.swift; sourceTree = ""; }; 3A2BCF51299F7724008BB5F3 /* CodableUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodableUtils.swift; sourceTree = ""; }; 3A580B4229E489D000C5C6F3 /* URLSession+body.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLSession+body.swift"; sourceTree = ""; }; @@ -230,10 +226,8 @@ 3AE3FB3929924CE100AFFC18 /* NSData+PHGGZIP.m */, 3AE3FB422992985A00AFFC18 /* Reachability.swift */, 3AE3FB462992AB0000AFFC18 /* Hedgelog.swift */, - 3A2BCF49299E2BDA008BB5F3 /* Swizzle.swift */, 3A2BCF51299F7724008BB5F3 /* CodableUtils.swift */, 3A0F108429C9ABB6002C0084 /* ReadWriteLock.swift */, - 3A0F108629C9BD23002C0084 /* MethodSwizzler.swift */, 3A0F108829C9BD76002C0084 /* Errors.swift */, ); path = Utils; @@ -264,6 +258,7 @@ 3AC745B7296D6FE60025C109 /* PostHog */ = { isa = PBXGroup; children = ( + 69779BED2AE6B29E00D7A48E /* Models */, 3AC745B8296D6FE60025C109 /* PostHog.h */, 3AA4C09B2988315D006C4731 /* Utils */, 3AE3FB36299162EA00AFFC18 /* PostHogApi.swift */, @@ -274,7 +269,6 @@ 3AE3FB48299391DF00AFFC18 /* PostHogStorage.swift */, 69261D122AD5685B00232EC7 /* PostHogFeatureFlags.swift */, 69261D182AD9673500232EC7 /* PostHogBatchUploadInfo.swift */, - 69261D1A2AD9678C00232EC7 /* PostHogEvent.swift */, 69261D1C2AD967CD00232EC7 /* PostHogFileBackedQueue.swift */, 69261D1E2AD9681300232EC7 /* PostHogConsumerPayload.swift */, 69261D222AD9784200232EC7 /* PostHogVersion.swift */, @@ -306,6 +300,14 @@ name = Frameworks; sourceTree = ""; }; + 69779BED2AE6B29E00D7A48E /* Models */ = { + isa = PBXGroup; + children = ( + 69261D1A2AD9678C00232EC7 /* PostHogEvent.swift */, + ); + path = Models; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -495,8 +497,6 @@ 3AE3FB332991388500AFFC18 /* PostHogQueue.swift in Sources */, 3AE3FB3B29924CE100AFFC18 /* NSData+PHGGZIP.m in Sources */, 69261D1B2AD9678C00232EC7 /* PostHogEvent.swift in Sources */, - 3A2BCF4A299E2BDA008BB5F3 /* Swizzle.swift in Sources */, - 3A0F108729C9BD23002C0084 /* MethodSwizzler.swift in Sources */, 3AE3FB472992AB0000AFFC18 /* Hedgelog.swift in Sources */, 69261D132AD5685B00232EC7 /* PostHogFeatureFlags.swift in Sources */, 69261D1D2AD967CD00232EC7 /* PostHogFileBackedQueue.swift in Sources */, diff --git a/PostHog/PostHogEvent.swift b/PostHog/Models/PostHogEvent.swift similarity index 100% rename from PostHog/PostHogEvent.swift rename to PostHog/Models/PostHogEvent.swift diff --git a/PostHog/PostHogExtensions.swift b/PostHog/PostHogExtensions.swift index 4a5c252b28..ef34deeee5 100644 --- a/PostHog/PostHogExtensions.swift +++ b/PostHog/PostHogExtensions.swift @@ -16,7 +16,5 @@ import Foundation public extension PostHogSDK { static let didStartNotification = Notification.Name("PostHogDidStart") // object: nil - static let didStartRecordingNotification = Notification.Name("PostHogDidStartRecording") // object: nil - static let didResetSessionNotification = Notification.Name("PostHogDidResetSession") // object: String static let didReceiveFeatureFlags = Notification.Name("PostHogDidReceiveFeatureFlags") // object: nil } diff --git a/PostHog/Utils/MethodSwizzler.swift b/PostHog/Utils/MethodSwizzler.swift deleted file mode 100644 index d5ab6a888f..0000000000 --- a/PostHog/Utils/MethodSwizzler.swift +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0. - * This product includes software developed at Datadog (https://www.datadoghq.com/). - * Copyright 2019-Present Datadog, Inc. - */ - -import Foundation - -class MethodSwizzler { - struct FoundMethod: Hashable { - let method: Method - let klass: AnyClass - - fileprivate init(method: Method, klass: AnyClass) { - self.method = method - self.klass = klass - } - - static func == (lhs: FoundMethod, rhs: FoundMethod) -> Bool { - let methodParity = (lhs.method == rhs.method) - let classParity = (NSStringFromClass(lhs.klass) == NSStringFromClass(rhs.klass)) - return methodParity && classParity - } - - func hash(into hasher: inout Hasher) { - let methodName = NSStringFromSelector(method_getName(method)) - let klassName = NSStringFromClass(klass) - let identifier = "\(methodName)|||\(klassName)" - hasher.combine(identifier) - } - } - - private var implementationCache: [FoundMethod: IMP] = [:] - var swizzledMethods: [FoundMethod] { - Array(implementationCache.keys) - } - - static func findMethod(with selector: Selector, in klass: AnyClass) throws -> FoundMethod { - /// NOTE: RUMM-452 as we never add/remove methods/classes at runtime, - /// search operation doesn't have to wrapped in sync {...} although it's visible in the interface - var headKlass: AnyClass? = klass - while let someKlass = headKlass { - if let foundMethod = findMethod(with: selector, in: someKlass) { - return FoundMethod(method: foundMethod, klass: someKlass) - } - headKlass = class_getSuperclass(headKlass) - } - throw InternalPostHogError(description: "\(NSStringFromSelector(selector)) is not found in \(NSStringFromClass(klass))") - } - - func originalImplementation(of found: FoundMethod) -> TypedIMP { - sync { - let originalImp: IMP = implementationCache[found] ?? method_getImplementation(found.method) - return unsafeBitCast(originalImp, to: TypedIMP.self) - } - } - - func swizzle( - _ foundMethod: FoundMethod, - impProvider: (TypedIMP) -> TypedBlockIMP - ) { - sync { - let currentIMP = method_getImplementation(foundMethod.method) - let current_typedIMP = unsafeBitCast(currentIMP, to: TypedIMP.self) - let newImpBlock: TypedBlockIMP = impProvider(current_typedIMP) - let newImp: IMP = imp_implementationWithBlock(newImpBlock) - - set(newIMP: newImp, for: foundMethod) - } - } - - /// Removes swizzling and resets the method to its original implementation. - func unswizzle() { - for foundMethod in swizzledMethods { - let originalTypedIMP = originalImplementation(of: foundMethod) - let originalIMP: IMP = unsafeBitCast(originalTypedIMP, to: IMP.self) - method_setImplementation(foundMethod.method, originalIMP) - } - } - - // MARK: - Private methods - - @discardableResult - private func sync(block: () -> T) -> T { - objc_sync_enter(self) - defer { objc_sync_exit(self) } - return block() - } - - private static func findMethod(with selector: Selector, in klass: AnyClass) -> Method? { - var methodsCount: UInt32 = 0 - let methodsCountPtr = withUnsafeMutablePointer(to: &methodsCount) { $0 } - guard let methods: UnsafeMutablePointer = class_copyMethodList(klass, methodsCountPtr) else { - return nil - } - defer { - free(methods) - } - for index in 0 ..< Int(methodsCount) { - let method = methods.advanced(by: index).pointee - if method_getName(method) == selector { - return method - } - } - return nil - } - - private func set(newIMP: IMP, for found: FoundMethod) { - if implementationCache[found] == nil { - implementationCache[found] = method_getImplementation(found.method) - } - method_setImplementation(found.method, newIMP) - } -} - -extension MethodSwizzler.FoundMethod { - var swizzlingName: String { "\(klass).\(method_getName(method))" } -} diff --git a/PostHog/Utils/Swizzle.swift b/PostHog/Utils/Swizzle.swift deleted file mode 100644 index 0cf28f1487..0000000000 --- a/PostHog/Utils/Swizzle.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// Swizzle.swift -// PostHog -// -// Created by Ben White on 16.02.23. -// - -import Foundation - -func swizzle(selector originalSelector: Selector, with swizzledSelector: Selector, inClass: AnyClass, usingClass: AnyClass) { - guard let originalMethod = class_getInstanceMethod(inClass, originalSelector), - let swizzledMethod = class_getInstanceMethod(usingClass, swizzledSelector) - else { return } - - if class_addMethod(inClass, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)) { - class_replaceMethod(inClass, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)) - } else { - method_exchangeImplementations(originalMethod, swizzledMethod) - } -} diff --git a/PostHogExample/AppDelegate.swift b/PostHogExample/AppDelegate.swift index 4eaa8c035d..94cea027b9 100644 --- a/PostHogExample/AppDelegate.swift +++ b/PostHogExample/AppDelegate.swift @@ -28,7 +28,20 @@ class AppDelegate: NSObject, UIApplicationDelegate { // "iteration": iteration // ]) // } + + let defaultCenter = NotificationCenter.default + + #if os(iOS) || os(tvOS) + defaultCenter.addObserver(self, + selector: #selector(self.receiveFeatureFlags), + name: PostHogSDK.didReceiveFeatureFlags, + object: nil) + #endif return true } + + @objc func receiveFeatureFlags() { + print("receiveFeatureFlags") + } }