From d5540ae1ab9bfb2528232bea6894788099ccc55a Mon Sep 17 00:00:00 2001 From: Rodrigo Gomez Palacio Date: Wed, 16 Oct 2024 14:02:59 -0500 Subject: [PATCH] OSConsistencyKey Implementation & replacement for previous enum Motivation: we need `setRywToken` to be extensible to future consistency use-cases. Here we are replacing the specific OSIamFetchOffsetKey enum argument type with a type-erased wrapper class we can use factor methods on to get the raw value. The reason we have to do it this way is because swift enums cannot conform to class-bound protocols or generics. --- .../OneSignal.xcodeproj/project.pbxproj | 8 ++--- .../IamFetch/OSIamFetchOffsetKey.swift | 2 +- ...cyKeyEnum.swift => OSConsistencyKey.swift} | 35 ++++++++++++++++++- .../Consistency/OSConsistencyManager.swift | 4 +-- .../OSPropertyOperationExecutor.swift | 6 +++- .../OSSubscriptionOperationExecutor.swift | 12 +++++-- .../Source/Executors/OSUserExecutor.swift | 6 +++- 7 files changed, 61 insertions(+), 12 deletions(-) rename iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/{OSConsistencyKeyEnum.swift => OSConsistencyKey.swift} (50%) diff --git a/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj b/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj index 98c26f186..d1385c6a6 100644 --- a/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj +++ b/iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj @@ -236,9 +236,9 @@ 5B053FBC2CAE07EB002F30C4 /* OneSignalOSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C115161289A259500565C41 /* OneSignalOSCore.framework */; }; 5B053FC32CAE0843002F30C4 /* OSConsistencyManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC1DE672C90C23E00CA8807 /* OSConsistencyManagerTests.swift */; }; 5B58E4F8237CE7B4009401E0 /* UIDeviceOverrider.m in Sources */ = {isa = PBXBuildFile; fileRef = 5B58E4F6237CE7B4009401E0 /* UIDeviceOverrider.m */; }; + 5B58F09B2CC0419100298493 /* OSConsistencyKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B58F09A2CC0419100298493 /* OSConsistencyKey.swift */; }; 5BC1DE5C2C90B7E600CA8807 /* OSConsistencyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC1DE5B2C90B7E600CA8807 /* OSConsistencyManager.swift */; }; 5BC1DE5E2C90B80E00CA8807 /* OSCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC1DE5D2C90B80E00CA8807 /* OSCondition.swift */; }; - 5BC1DE602C90B83900CA8807 /* OSConsistencyKeyEnum.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC1DE5F2C90B83900CA8807 /* OSConsistencyKeyEnum.swift */; }; 5BC1DE622C90B85A00CA8807 /* OSIamFetchOffsetKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC1DE612C90B85A00CA8807 /* OSIamFetchOffsetKey.swift */; }; 5BC1DE642C90BB9000CA8807 /* OSIamFetchReadyCondition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BC1DE632C90BB9000CA8807 /* OSIamFetchReadyCondition.swift */; }; 7A123295235DFE3B002B6CE3 /* OutcomeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A123294235DFE3B002B6CE3 /* OutcomeTests.m */; }; @@ -1382,9 +1382,9 @@ 5B053FB82CAE07EB002F30C4 /* OneSignalOSCoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OneSignalOSCoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 5B58E4F3237CE7B3009401E0 /* UIDeviceOverrider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIDeviceOverrider.h; sourceTree = ""; }; 5B58E4F6237CE7B4009401E0 /* UIDeviceOverrider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIDeviceOverrider.m; sourceTree = ""; }; + 5B58F09A2CC0419100298493 /* OSConsistencyKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSConsistencyKey.swift; sourceTree = ""; }; 5BC1DE5B2C90B7E600CA8807 /* OSConsistencyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSConsistencyManager.swift; sourceTree = ""; }; 5BC1DE5D2C90B80E00CA8807 /* OSCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSCondition.swift; sourceTree = ""; }; - 5BC1DE5F2C90B83900CA8807 /* OSConsistencyKeyEnum.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSConsistencyKeyEnum.swift; sourceTree = ""; }; 5BC1DE612C90B85A00CA8807 /* OSIamFetchOffsetKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSIamFetchOffsetKey.swift; sourceTree = ""; }; 5BC1DE632C90BB9000CA8807 /* OSIamFetchReadyCondition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSIamFetchReadyCondition.swift; sourceTree = ""; }; 5BC1DE672C90C23E00CA8807 /* OSConsistencyManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSConsistencyManagerTests.swift; sourceTree = ""; }; @@ -2357,7 +2357,7 @@ 5BC1DE662C90BCD100CA8807 /* IamFetch */, 5BC1DE5B2C90B7E600CA8807 /* OSConsistencyManager.swift */, 5BC1DE5D2C90B80E00CA8807 /* OSCondition.swift */, - 5BC1DE5F2C90B83900CA8807 /* OSConsistencyKeyEnum.swift */, + 5B58F09A2CC0419100298493 /* OSConsistencyKey.swift */, ); path = Consistency; sourceTree = ""; @@ -4148,12 +4148,12 @@ buildActionMask = 2147483647; files = ( DEFB3E652BB7346D00E65DAD /* OSLiveActivities.swift in Sources */, - 5BC1DE602C90B83900CA8807 /* OSConsistencyKeyEnum.swift in Sources */, 3C4F9E4428A4466C009F453A /* OSOperationRepo.swift in Sources */, 3C11518B289ADEEB00565C41 /* OSEventProducer.swift in Sources */, 3C115165289A259500565C41 /* OneSignalOSCore.docc in Sources */, 5BC1DE5E2C90B80E00CA8807 /* OSCondition.swift in Sources */, 5BC1DE5C2C90B7E600CA8807 /* OSConsistencyManager.swift in Sources */, + 5B58F09B2CC0419100298493 /* OSConsistencyKey.swift in Sources */, 3C115189289ADEA300565C41 /* OSModelStore.swift in Sources */, 3C115185289ADE4F00565C41 /* OSModel.swift in Sources */, 3CF1A5632C669EA40056B3AA /* OSNewRecordsState.swift in Sources */, diff --git a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/IamFetch/OSIamFetchOffsetKey.swift b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/IamFetch/OSIamFetchOffsetKey.swift index f8d40048a..653b1fa95 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/IamFetch/OSIamFetchOffsetKey.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/IamFetch/OSIamFetchOffsetKey.swift @@ -27,7 +27,7 @@ import Foundation -@objc public enum OSIamFetchOffsetKey: Int, OSConsistencyKeyEnum, Hashable { +@objc public enum OSIamFetchOffsetKey: Int { case user = 0 case subscription = 1 } diff --git a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/OSConsistencyKeyEnum.swift b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/OSConsistencyKey.swift similarity index 50% rename from iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/OSConsistencyKeyEnum.swift rename to iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/OSConsistencyKey.swift index fcacaa909..6ff888dbf 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/OSConsistencyKeyEnum.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/OSConsistencyKey.swift @@ -27,5 +27,38 @@ import Foundation -public protocol OSConsistencyKeyEnum: Hashable { +/** + A type-erased wrapper for enums to be compatible with Obj-C + + It allows the seamless use of swift enums with `Int` raw values since swift enums cannot conform to class-bound protocols. + They cannot be used with generic @objc initializers either. + + This wrapper stores the `rawValue` of **any** enum & exposes factory methods for each supported enum. + + Instructions: As needed we can add new enums for new consistency use-cases by providing additional factory methods that initialize + the wrapper with the enum's `rawValue`. + */ +@objc public class OSConsistencyKey: NSObject { + private let value: Int + + // Private initializer to store the raw value. + private init(value: Int) { + self.value = value + } + + // Expose the rawValue to Objective-C. + @objc public func rawValue() -> Int { + return value + } + + /* F A C T O R Y M E T H O D S */ + + // Example: + // @objc public static func fromSomeNewKey(_ key: OSSomeNewKey) -> OSConsistencyKey { + // return OSConsistencyKey(value: key.rawValue) + // } + + @objc public static func fromIamFetchOffsetKey(_ key: OSIamFetchOffsetKey) -> OSConsistencyKey { + return OSConsistencyKey(value: key.rawValue) + } } diff --git a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/OSConsistencyManager.swift b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/OSConsistencyManager.swift index 778182637..eaf6cee14 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/OSConsistencyManager.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Consistency/OSConsistencyManager.swift @@ -40,9 +40,9 @@ import OneSignalCore private override init() {} // Function to set the token in a thread-safe manner - @objc public func setRywToken(id: String, key: OSIamFetchOffsetKey, value: String?) { + @objc public func setRywToken(id: String, key: OSConsistencyKey, value: String?) { queue.sync { - let nsKey = NSNumber(value: key.rawValue) + let nsKey = NSNumber(value: key.rawValue()) if self.indexedTokens[id] == nil { self.indexedTokens[id] = [:] } diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSPropertyOperationExecutor.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSPropertyOperationExecutor.swift index 159fbe59d..507801afe 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSPropertyOperationExecutor.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSPropertyOperationExecutor.swift @@ -258,7 +258,11 @@ class OSPropertyOperationExecutor: OSOperationExecutor { if let onesignalId = request.identityModel.onesignalId { if let rywToken = response?["ryw_token"] as? String { - OSConsistencyManager.shared.setRywToken(id: onesignalId, key: OSIamFetchOffsetKey.user, value: rywToken) + OSConsistencyManager.shared.setRywToken( + id: onesignalId, + key: OSConsistencyKey.fromIamFetchOffsetKey(OSIamFetchOffsetKey.user), + value: rywToken + ) } else { // handle a potential regression where ryw_token is no longer returned by API OSConsistencyManager.shared.resolveConditionsWithID(id: OSIamFetchReadyCondition.CONDITIONID) diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSSubscriptionOperationExecutor.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSSubscriptionOperationExecutor.swift index 14da830ec..d53e75499 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSSubscriptionOperationExecutor.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSSubscriptionOperationExecutor.swift @@ -301,7 +301,11 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor { if let onesignalId = request.identityModel.onesignalId { if let rywToken = response["ryw_token"] as? String { - OSConsistencyManager.shared.setRywToken(id: onesignalId, key: OSIamFetchOffsetKey.subscription, value: rywToken) + OSConsistencyManager.shared.setRywToken( + id: onesignalId, + key: OSConsistencyKey.fromIamFetchOffsetKey(OSIamFetchOffsetKey.subscription), + value: rywToken + ) } else { // handle a potential regression where ryw_token is no longer returned by API OSConsistencyManager.shared.resolveConditionsWithID(id: OSIamFetchReadyCondition.CONDITIONID) @@ -418,7 +422,11 @@ class OSSubscriptionOperationExecutor: OSOperationExecutor { if let onesignalId = OneSignalUserManagerImpl.sharedInstance.onesignalId { if let rywToken = response?["ryw_token"] as? String { - OSConsistencyManager.shared.setRywToken(id: onesignalId, key: OSIamFetchOffsetKey.subscription, value: rywToken) + OSConsistencyManager.shared.setRywToken( + id: onesignalId, + key: OSConsistencyKey.fromIamFetchOffsetKey(OSIamFetchOffsetKey.subscription), + value: rywToken + ) } else { // handle a potential regression where ryw_token is no longer returned by API OSConsistencyManager.shared.resolveConditionsWithID(id: OSIamFetchReadyCondition.CONDITIONID) diff --git a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift index e9273e32b..5153b9a4f 100644 --- a/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift +++ b/iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift @@ -262,7 +262,11 @@ extension OSUserExecutor { if let onesignalId = request.identityModel.onesignalId { if let rywToken = response["ryw_token"] as? String { - OSConsistencyManager.shared.setRywToken(id: onesignalId, key: OSIamFetchOffsetKey.user, value: rywToken) + OSConsistencyManager.shared.setRywToken( + id: onesignalId, + key: OSConsistencyKey.fromIamFetchOffsetKey(OSIamFetchOffsetKey.user), + value: rywToken + ) } else { // handle a potential regression where ryw_token is no longer returned by API OSConsistencyManager.shared.resolveConditionsWithID(id: OSIamFetchReadyCondition.CONDITIONID)