From ee830eb8a68e7e9a445d348429ab440dfae3eb56 Mon Sep 17 00:00:00 2001 From: Nikola Zagorchev Date: Mon, 21 Nov 2022 16:31:00 +0200 Subject: [PATCH] Add multiple instance callbacks --- .../LeanplumSDK.xcodeproj/project.pbxproj | 12 ++++++++ .../Classes/CleverTapInstanceCallback.h | 25 ++++++++++++++++ .../Classes/CleverTapInstanceCallback.m | 30 +++++++++++++++++++ .../LeanplumSDK/Classes/Internal/Leanplum.m | 9 ++++-- LeanplumSDK/LeanplumSDK/Classes/Leanplum.h | 21 +++++++++---- LeanplumSDK/LeanplumSDK/Classes/LeanplumSDK.h | 1 + .../Migration/MigrationManager+API.swift | 11 +++++-- .../Migration/MigrationManager.swift | 9 ++---- .../Migration/Wrapper/CTWrapper.swift | 30 ++++++++++++------- .../Migration/Wrapper/Wrapper.swift | 6 ++-- .../Classes/Migration/CTWrapperTest.swift | 2 +- 11 files changed, 125 insertions(+), 31 deletions(-) create mode 100644 LeanplumSDK/LeanplumSDK/Classes/CleverTapInstanceCallback.h create mode 100644 LeanplumSDK/LeanplumSDK/Classes/CleverTapInstanceCallback.m diff --git a/LeanplumSDK/LeanplumSDK.xcodeproj/project.pbxproj b/LeanplumSDK/LeanplumSDK.xcodeproj/project.pbxproj index 1099ecdc..120879f4 100644 --- a/LeanplumSDK/LeanplumSDK.xcodeproj/project.pbxproj +++ b/LeanplumSDK/LeanplumSDK.xcodeproj/project.pbxproj @@ -214,6 +214,10 @@ 6A29EAC528EB56AD0024880E /* MigrationManager+ResponseHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A29EAC328EB56AD0024880E /* MigrationManager+ResponseHandler.swift */; }; 6A29EAF528EF37090024880E /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A29EAF428EF37090024880E /* IdentityManager.swift */; }; 6A29EAF628EF37090024880E /* IdentityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A29EAF428EF37090024880E /* IdentityManager.swift */; }; + 6A2E4C20292BAB3400385536 /* CleverTapInstanceCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A2E4C1E292BAB3400385536 /* CleverTapInstanceCallback.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6A2E4C21292BAB3400385536 /* CleverTapInstanceCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 6A2E4C1E292BAB3400385536 /* CleverTapInstanceCallback.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 6A2E4C22292BAB3400385536 /* CleverTapInstanceCallback.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A2E4C1F292BAB3400385536 /* CleverTapInstanceCallback.m */; }; + 6A2E4C23292BAB3400385536 /* CleverTapInstanceCallback.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A2E4C1F292BAB3400385536 /* CleverTapInstanceCallback.m */; }; 6A37A89628EF6E6C00F4339F /* Wrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A37A89528EF6E6C00F4339F /* Wrapper.swift */; }; 6A37A89728EF6E6C00F4339F /* Wrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A37A89528EF6E6C00F4339F /* Wrapper.swift */; }; 6A37A89928EF738200F4339F /* MigrationManager+API.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A37A89828EF738200F4339F /* MigrationManager+API.swift */; }; @@ -813,6 +817,8 @@ 6A29EABD28EA13B60024880E /* PropertyWrappers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyWrappers.swift; sourceTree = ""; }; 6A29EAC328EB56AD0024880E /* MigrationManager+ResponseHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MigrationManager+ResponseHandler.swift"; sourceTree = ""; }; 6A29EAF428EF37090024880E /* IdentityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityManager.swift; sourceTree = ""; }; + 6A2E4C1E292BAB3400385536 /* CleverTapInstanceCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CleverTapInstanceCallback.h; sourceTree = ""; }; + 6A2E4C1F292BAB3400385536 /* CleverTapInstanceCallback.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CleverTapInstanceCallback.m; sourceTree = ""; }; 6A37A89528EF6E6C00F4339F /* Wrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wrapper.swift; sourceTree = ""; }; 6A37A89828EF738200F4339F /* MigrationManager+API.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MigrationManager+API.swift"; sourceTree = ""; }; 6A37A89B28EF748800F4339F /* Dictionary+MapKeys.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+MapKeys.swift"; sourceTree = ""; }; @@ -920,6 +926,8 @@ 075AAD5B26847EC3007CA1BD /* MessageTemplates */, 075AAD8526847EC3007CA1BD /* Notifications */, 075AAD9526847EC3007CA1BD /* Utilities */, + 6A2E4C1E292BAB3400385536 /* CleverTapInstanceCallback.h */, + 6A2E4C1F292BAB3400385536 /* CleverTapInstanceCallback.m */, ); path = Classes; sourceTree = ""; @@ -1468,6 +1476,7 @@ 075AAE9C26847EC4007CA1BD /* Leanplum_Reachability.h in Headers */, 075AAE1826847EC4007CA1BD /* LPFileTransferManager.h in Headers */, 075AAE7E26847EC4007CA1BD /* LPAES.h in Headers */, + 6A2E4C20292BAB3400385536 /* CleverTapInstanceCallback.h in Headers */, 075AAE9726847EC4007CA1BD /* Leanplum_SocketIO.h in Headers */, 075AAE3026847EC4007CA1BD /* LPVar.h in Headers */, 075AAE0626847EC4007CA1BD /* LPRequestBatch.h in Headers */, @@ -1555,6 +1564,7 @@ 6A714B0B26F8B317004A34A9 /* Leanplum_Reachability.h in Headers */, 6A714B0C26F8B317004A34A9 /* LPFileTransferManager.h in Headers */, 6A714B0D26F8B317004A34A9 /* LPAES.h in Headers */, + 6A2E4C21292BAB3400385536 /* CleverTapInstanceCallback.h in Headers */, 6A714B0E26F8B317004A34A9 /* Leanplum_SocketIO.h in Headers */, 6A714B0F26F8B317004A34A9 /* LPVar.h in Headers */, 6A714B1026F8B317004A34A9 /* LPRequestBatch.h in Headers */, @@ -1940,6 +1950,7 @@ 6A07FDA22811911000995BE3 /* ActionManager+FileDownload.swift in Sources */, 075AAE8126847EC4007CA1BD /* LPSwizzle.m in Sources */, 6AD978542774F2F700A7C6C6 /* NotificationsProxy+iOS9.swift in Sources */, + 6A2E4C22292BAB3400385536 /* CleverTapInstanceCallback.m in Sources */, 075AAE6A26847EC4007CA1BD /* LPLocalNotificationsManager.m in Sources */, C9D064DC2775DB1100A7A5F9 /* Dictionary+Equatable.swift in Sources */, 075AAE1C26847EC4007CA1BD /* LPNetworkFactory.m in Sources */, @@ -2068,6 +2079,7 @@ 6A07FDA32811911000995BE3 /* ActionManager+FileDownload.swift in Sources */, 6A714B9126F8B317004A34A9 /* LPSwizzle.m in Sources */, 6AD978552774F2F700A7C6C6 /* NotificationsProxy+iOS9.swift in Sources */, + 6A2E4C23292BAB3400385536 /* CleverTapInstanceCallback.m in Sources */, 6A714B9226F8B317004A34A9 /* LPLocalNotificationsManager.m in Sources */, C9D064DD2775DB1100A7A5F9 /* Dictionary+Equatable.swift in Sources */, 6A714B9326F8B317004A34A9 /* LPNetworkFactory.m in Sources */, diff --git a/LeanplumSDK/LeanplumSDK/Classes/CleverTapInstanceCallback.h b/LeanplumSDK/LeanplumSDK/Classes/CleverTapInstanceCallback.h new file mode 100644 index 00000000..26d1321d --- /dev/null +++ b/LeanplumSDK/LeanplumSDK/Classes/CleverTapInstanceCallback.h @@ -0,0 +1,25 @@ +// +// CleverTapInstanceCallback.h +// LeanplumSDK +// +// Created by Nikola Zagorchev on 21.11.22. +// Copyright © 2022 Leanplum. All rights reserved. + +#import +// Forward declaration for CleverTap instance +@class CleverTap; + +NS_ASSUME_NONNULL_BEGIN + +typedef void (^LeanplumCleverTapInstanceBlock)(CleverTap* instance); + +@interface CleverTapInstanceCallback : NSObject + +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithCallback:(LeanplumCleverTapInstanceBlock)block; + +- (void)onInstance:(CleverTap *)instance; + +@end + +NS_ASSUME_NONNULL_END diff --git a/LeanplumSDK/LeanplumSDK/Classes/CleverTapInstanceCallback.m b/LeanplumSDK/LeanplumSDK/Classes/CleverTapInstanceCallback.m new file mode 100644 index 00000000..f6197641 --- /dev/null +++ b/LeanplumSDK/LeanplumSDK/Classes/CleverTapInstanceCallback.m @@ -0,0 +1,30 @@ +// +// CleverTapInstanceCallback.m +// LeanplumSDK +// +// Created by Nikola Zagorchev on 21.11.22. +// Copyright © 2022 Leanplum. All rights reserved. + +#import "CleverTapInstanceCallback.h" + +@interface CleverTapInstanceCallback() +@property (atomic, nonnull) LeanplumCleverTapInstanceBlock block; +@end + +@implementation CleverTapInstanceCallback + +- (instancetype)initWithCallback:(LeanplumCleverTapInstanceBlock)block +{ + self = [super init]; + if (self) { + self.block = block; + } + return self; +} + +- (void)onInstance:(CleverTap *)instance +{ + self.block(instance); +} + +@end diff --git a/LeanplumSDK/LeanplumSDK/Classes/Internal/Leanplum.m b/LeanplumSDK/LeanplumSDK/Classes/Internal/Leanplum.m index 777441ef..926c98c5 100644 --- a/LeanplumSDK/LeanplumSDK/Classes/Internal/Leanplum.m +++ b/LeanplumSDK/LeanplumSDK/Classes/Internal/Leanplum.m @@ -2621,9 +2621,14 @@ + (void)enableProvisionalPushNotifications [[Leanplum notificationsManager] enableProvisionalPush]; } -+ (void)onCleverTapInstanceInitialized:(LeanplumCleverTapInstanceBlock)block ++ (void)addCleverTapInstanceCallback:(CleverTapInstanceCallback *)callback { - [[MigrationManager shared] setInstanceCallback:block]; + [[MigrationManager shared] addInstanceCallback:callback]; +} + ++ (void)removeCleverTapInstanceCallback:(CleverTapInstanceCallback *)callback +{ + [[MigrationManager shared] removeInstanceCallback:callback]; } - (void) dealloc { diff --git a/LeanplumSDK/LeanplumSDK/Classes/Leanplum.h b/LeanplumSDK/LeanplumSDK/Classes/Leanplum.h index 769cec4d..e43b847a 100644 --- a/LeanplumSDK/LeanplumSDK/Classes/Leanplum.h +++ b/LeanplumSDK/LeanplumSDK/Classes/Leanplum.h @@ -64,8 +64,7 @@ #import "LPLogManager.h" #import "LPRequestSenderTimer.h" #import "LPRequestSender.h" -// Forward declaration for CleverTap instance -@class CleverTap; +#import "CleverTapInstanceCallback.h" NS_ASSUME_NONNULL_BEGIN @@ -147,7 +146,6 @@ typedef BOOL (^LeanplumActionBlock)(LPActionContext* context); typedef void (^LeanplumHandleNotificationBlock)(void); typedef void (^LeanplumShouldHandleNotificationBlock)(NSDictionary *userInfo, LeanplumHandleNotificationBlock response); typedef void (^LeanplumPushSetupBlock)(void); -typedef void (^LeanplumCleverTapInstanceBlock)(CleverTap* instance); /**@}*/ /** @@ -805,12 +803,23 @@ NS_SWIFT_NAME(setDeviceLocation(latitude:longitude:city:region:country:type:)); /** * Block to call when CleverTapAPI instance is created. - * CleverTapSDK must be imported to use this method. + * __CleverTapSDK must be imported to use this method.__ * Use the instance for any CleverTap work. * - * @param block Null value will remove the callback. + * @remark CleverTapSDK must be imported to use the `CleverTapInstanceCallback`. + * + * @param callback Null value will remove the callback. + */ ++ (void)addCleverTapInstanceCallback:(CleverTapInstanceCallback *)callback +NS_SWIFT_NAME(addCleverTapInstance(callback:)); + +/** + * Removes the callback for the CleverTap instance. + * + * @param callback Callback to remove. */ -+ (void)onCleverTapInstanceInitialized:(LeanplumCleverTapInstanceBlock)block; ++ (void)removeCleverTapInstanceCallback:(CleverTapInstanceCallback *)callback +NS_SWIFT_NAME(removeCleverTapInstance(callback:)); @end diff --git a/LeanplumSDK/LeanplumSDK/Classes/LeanplumSDK.h b/LeanplumSDK/LeanplumSDK/Classes/LeanplumSDK.h index a04cf278..873d940a 100644 --- a/LeanplumSDK/LeanplumSDK/Classes/LeanplumSDK.h +++ b/LeanplumSDK/LeanplumSDK/Classes/LeanplumSDK.h @@ -109,3 +109,4 @@ FOUNDATION_EXPORT const unsigned char LeanplumSDKVersionString[]; #import "UIDevice+IdentifierAddition.h" #import "Leanplum_AsyncSocket.h" #import "Leanplum_WebSocket.h" +#import "CleverTapInstanceCallback.h" diff --git a/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager+API.swift b/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager+API.swift index f59fda43..618fbc1b 100644 --- a/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager+API.swift +++ b/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager+API.swift @@ -63,8 +63,15 @@ wrapper?.setTrafficSourceInfo(info) } - func setInstanceCallback(_ callback: @escaping ((Any) -> Void)) { - instanceCallback = callback + func addInstanceCallback(_ callback: CleverTapInstanceCallback) { + instanceCallbacks.append(callback) + wrapper?.addInstanceCallback(callback) + } + + func removeInstanceCallback(_ callback: CleverTapInstanceCallback) { + guard let index = instanceCallbacks.firstIndex(of: callback) else { return } + instanceCallbacks.remove(at: index) + wrapper?.removeInstanceCallback(callback) } func setLogLevel(_ level: LeanplumLogLevel) { diff --git a/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager.swift b/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager.swift index a297d7c9..8076c361 100644 --- a/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager.swift +++ b/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/MigrationManager.swift @@ -16,6 +16,7 @@ import Foundation @objc public static let shared: MigrationManager = .init() var wrapper: Wrapper? + var instanceCallbacks: [CleverTapInstanceCallback] = [] @StringOptionalUserDefaults(key: Constants.HashKey) var migrationHash: String? @@ -43,12 +44,6 @@ import Foundation private let lock = NSLock() - var instanceCallback: ((Any) -> Void)? { - didSet { - wrapper?.setInstanceCallback(instanceCallback) - } - } - // Expose to ObjC @objc public var useLeanplum: Bool { migrationState.useLeanplum @@ -73,7 +68,7 @@ import Foundation wrapper = CTWrapper(accountId: id, accountToken: token, accountRegion: accountRegion, userId: user, deviceId: device, - callback: instanceCallback) + callbacks: instanceCallbacks) if Leanplum.hasStarted() { Log.debug("[Wrapper] Leanplum has already started, launching CleverTap as well.") diff --git a/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/Wrapper/CTWrapper.swift b/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/Wrapper/CTWrapper.swift index fd13302d..7175e1fe 100644 --- a/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/Wrapper/CTWrapper.swift +++ b/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/Wrapper/CTWrapper.swift @@ -28,7 +28,7 @@ class CTWrapper: Wrapper { // MARK: Initialization var cleverTapInstance: CleverTap? - var instanceCallback: ((Any) -> Void)? + var instanceCallbacks: [CleverTapInstanceCallback] var accountId: String var accountToken: String @@ -40,12 +40,12 @@ class CTWrapper: Wrapper { accountRegion: String, userId: String, deviceId: String, - callback: ((Any) -> Void)?) { + callbacks: [CleverTapInstanceCallback]) { Log.debug("[Wrapper] Wrapper Instantiated") self.accountId = accountId self.accountToken = accountToken self.accountRegion = accountRegion - self.instanceCallback = callback + self.instanceCallbacks = callbacks identityManager = IdentityManager(userId: userId, deviceId: deviceId) setLogLevel(LPLogManager.logLevel()) @@ -76,20 +76,28 @@ class CTWrapper: Wrapper { cleverTapInstance?.profilePush([Constants.AnonymousDeviceUserProperty: identityManager.deviceId]) } } - triggerInstanceCallback() + triggerInstanceCallbacks() } // MARK: Callback - func setInstanceCallback(_ callback: ((Any) -> Void)?) { - instanceCallback = callback - triggerInstanceCallback() + func addInstanceCallback(_ callback: CleverTapInstanceCallback) { + instanceCallbacks.append(callback) + if let instance = cleverTapInstance { + callback.onInstance(instance) + } } - private func triggerInstanceCallback() { - guard let callback = instanceCallback, let instance = cleverTapInstance else { - return + func removeInstanceCallback(_ callback: CleverTapInstanceCallback) { + guard let index = instanceCallbacks.firstIndex(of: callback) else { return } + instanceCallbacks.remove(at: index) + } + + private func triggerInstanceCallbacks() { + guard let instance = cleverTapInstance else { return } + + for callback in instanceCallbacks { + callback.onInstance(instance) } - callback(instance) } // MARK: Tracking diff --git a/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/Wrapper/Wrapper.swift b/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/Wrapper/Wrapper.swift index 9fc2f313..a2704e01 100644 --- a/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/Wrapper/Wrapper.swift +++ b/LeanplumSDK/LeanplumSDK/ClassesSwift/Migration/Wrapper/Wrapper.swift @@ -10,8 +10,10 @@ protocol Wrapper { /// equivalent to Leanplum start func launch() - /// Sets instance callback when wrapper has initialized - func setInstanceCallback(_ callback: ((Any) -> Void)?) + /// Adds instance callback, executed when wrapper has initialized + func addInstanceCallback(_ callback: CleverTapInstanceCallback) + + func removeInstanceCallback(_ callback: CleverTapInstanceCallback) func track(_ eventName: String?, value: Double, info: String?, params: [String: Any]) diff --git a/LeanplumSDKApp/LeanplumSDKTests/Classes/Migration/CTWrapperTest.swift b/LeanplumSDKApp/LeanplumSDKTests/Classes/Migration/CTWrapperTest.swift index 72b355cf..c635ad9e 100644 --- a/LeanplumSDKApp/LeanplumSDKTests/Classes/Migration/CTWrapperTest.swift +++ b/LeanplumSDKApp/LeanplumSDKTests/Classes/Migration/CTWrapperTest.swift @@ -12,7 +12,7 @@ import XCTest class WrapperTest: XCTestCase { static let attributeMappings = ["lpName": "ctName", "lpName2": "ctName2"] - let wrapper = CTWrapper(accountId: "", accountToken: "", accountRegion: "", userId: "", deviceId: "", callback: nil) + let wrapper = CTWrapper(accountId: "", accountToken: "", accountRegion: "", userId: "", deviceId: "", callbacks: []) override class func setUp() { MigrationManager.shared.attributeMappings = attributeMappings