From 87d1e635cc4ae5d3c496c29433dc3ff7612c3c06 Mon Sep 17 00:00:00 2001 From: zapcannon87 Date: Thu, 12 May 2022 18:26:22 +0800 Subject: [PATCH] feat(im): disabling auto-binding current/default installation and client --- .../LeanCloudObjcTests/IMClientTestCase.swift | 42 +++++++++- .../LCIMClientTestCase.swift | 4 +- AVOS/Sources/Realtime/IM/Client/LCIMClient.h | 44 ++++++++++ AVOS/Sources/Realtime/IM/Client/LCIMClient.m | 81 +++++++++++++------ .../Realtime/IM/Client/LCIMClient_Internal.h | 2 + 5 files changed, 146 insertions(+), 27 deletions(-) diff --git a/AVOS/LeanCloudObjcTests/IMClientTestCase.swift b/AVOS/LeanCloudObjcTests/IMClientTestCase.swift index 47f90d43..591b5c2a 100644 --- a/AVOS/LeanCloudObjcTests/IMClientTestCase.swift +++ b/AVOS/LeanCloudObjcTests/IMClientTestCase.swift @@ -151,6 +151,44 @@ class IMClientTestCase: RTMBaseTestCase { NotificationCenter.default.removeObserver(observer) } } + + func testDisableAutoBindingInstallation() { + let installation = LCInstallation.default() + let option = LCIMClientOption() + option.isAutoBindingInstallationDisabled = true + let client = try! LCIMClient(clientId: uuid, option: option) + XCTAssertNil(client.installation) + XCTAssertNil(client.currentDeviceToken) + expecting { (exp) in + client.open { (success, error) in + XCTAssertTrue(success) + XCTAssertNil(error) + exp.fulfill() + } + } + let deviceToken = uuid + var observer: NSObjectProtocol? + expecting(timeout: 5, expectation: { + let exp = self.expectation(description: "will not upload deviceToken") + exp.expectedFulfillmentCount = 1 + exp.isInverted = true + return exp + }) { (exp) in + observer = NotificationCenter.default.addObserver( + forName: NSNotification.Name(rawValue: "Test.LCIMClient.reportDeviceToken"), + object: nil, + queue: .main) + { (notification) in + XCTAssertNil(notification.userInfo?["error"]) + exp.fulfill() + } + installation.setDeviceTokenHexString(deviceToken, teamId: "LeanCloud") + } + XCTAssertNil(client.installation) + XCTAssertNil(client.currentDeviceToken) + XCTAssertNotNil(observer) + if let observer = observer { + NotificationCenter.default.removeObserver(observer) + } + } } - - diff --git a/AVOS/LeanCloudObjcTests/LCIMClientTestCase.swift b/AVOS/LeanCloudObjcTests/LCIMClientTestCase.swift index 3afdca07..971b9877 100644 --- a/AVOS/LeanCloudObjcTests/LCIMClientTestCase.swift +++ b/AVOS/LeanCloudObjcTests/LCIMClientTestCase.swift @@ -250,7 +250,7 @@ class LCIMClientTestCase: RTMBaseTestCase { XCTAssertTrue(installation1.save()) let delegator1 = LCIMClientDelegator.init() - let client1: LCIMClient! = try? LCIMClient.init(clientId: clientID, tag: tag, installation: installation1) + let client1: LCIMClient! = try? LCIMClient.init(clientId: clientID, tag: tag, option: nil, installation: installation1) XCTAssertNotNil(client1) client1.delegate = delegator1 expecting { (exp) in @@ -269,7 +269,7 @@ class LCIMClientTestCase: RTMBaseTestCase { XCTAssertTrue(installation2.save()) let delegator2 = LCIMClientDelegator.init() - let client2: LCIMClient! = try? LCIMClient.init(clientId: clientID, tag: tag, installation: installation2) + let client2: LCIMClient! = try? LCIMClient.init(clientId: clientID, tag: tag, option: nil, installation: installation2) XCTAssertNotNil(client2) client2.delegate = delegator2 diff --git a/AVOS/Sources/Realtime/IM/Client/LCIMClient.h b/AVOS/Sources/Realtime/IM/Client/LCIMClient.h index e86fcd33..9f49f935 100644 --- a/AVOS/Sources/Realtime/IM/Client/LCIMClient.h +++ b/AVOS/Sources/Realtime/IM/Client/LCIMClient.h @@ -36,6 +36,14 @@ NS_ASSUME_NONNULL_BEGIN @end +/// The option of the client. +@interface LCIMClientOption : NSObject + +/// Set with `true` means disabling auto-binding current/default installation and client. +@property (nonatomic) BOOL isAutoBindingInstallationDisabled; + +@end + /// IM Client. @interface LCIMClient : NSObject @@ -75,6 +83,14 @@ NS_ASSUME_NONNULL_BEGIN - (nullable instancetype)initWithClientId:(NSString *)clientId error:(NSError * __autoreleasing *)error; +/// Initializing with an ID and an option. +/// @param clientId The length of the ID should in range `[1, 64]`. +/// @param option See `LCIMClientOption`. +/// @param error Throws exception when error occurred. +- (nullable instancetype)initWithClientId:(NSString *)clientId + option:(LCIMClientOption * _Nullable)option + error:(NSError * __autoreleasing *)error; + /// Initializing with an ID and a tag. /// @param clientId The length of the ID should in range `[1, 64]`. /// @param tag Using a tag to specify the context, `@"default"` is reserved. @@ -83,12 +99,30 @@ NS_ASSUME_NONNULL_BEGIN tag:(NSString * _Nullable)tag error:(NSError * __autoreleasing *)error; +/// Initializing with an ID, a tag and an option. +/// @param clientId The length of the ID should in range `[1, 64]`. +/// @param tag Using a tag to specify the context, `@"default"` is reserved. +/// @param option See `LCIMClientOption`. +/// @param error Throws exception when error occurred. +- (nullable instancetype)initWithClientId:(NSString *)clientId + tag:(NSString * _Nullable)tag + option:(LCIMClientOption * _Nullable)option + error:(NSError * __autoreleasing *)error; + /// Initializing with an `LCUser`. /// @param user The user should have logged in. /// @param error Throws exception when error occurred. - (nullable instancetype)initWithUser:(LCUser *)user error:(NSError * __autoreleasing *)error; +/// Initializing with an `LCUser` and an option. +/// @param user The user should have logged in. +/// @param option See `LCIMClientOption`. +/// @param error Throws exception when error occurred. +- (nullable instancetype)initWithUser:(LCUser *)user + option:(LCIMClientOption * _Nullable)option + error:(NSError * __autoreleasing *)error; + /// Initializing with an `LCUser` and a tag. /// @param user The user should have logged in. /// @param tag Using a tag to specify the context, `@"default"` is reserved. @@ -97,6 +131,16 @@ NS_ASSUME_NONNULL_BEGIN tag:(NSString * _Nullable)tag error:(NSError * __autoreleasing *)error; +/// Initializing with an `LCUser`, a tag and an option. +/// @param user The user should have logged in. +/// @param tag Using a tag to specify the context, `@"default"` is reserved. +/// @param option See `LCIMClientOption`. +/// @param error Throws exception when error occurred. +- (nullable instancetype)initWithUser:(LCUser *)user + tag:(NSString * _Nullable)tag + option:(LCIMClientOption * _Nullable)option + error:(NSError * __autoreleasing *)error; + // MARK: Open & Close /// Open this client before using instant messaging service, diff --git a/AVOS/Sources/Realtime/IM/Client/LCIMClient.m b/AVOS/Sources/Realtime/IM/Client/LCIMClient.m index 44cd5ab3..b44a0ba2 100644 --- a/AVOS/Sources/Realtime/IM/Client/LCIMClient.m +++ b/AVOS/Sources/Realtime/IM/Client/LCIMClient.m @@ -47,6 +47,10 @@ - (instancetype)init { @end +@implementation LCIMClientOption + +@end + @implementation LCIMClient { LCIMClientStatus _status; } @@ -75,41 +79,64 @@ - (instancetype)init - (instancetype)initWithClientId:(NSString *)clientId error:(NSError *__autoreleasing _Nullable *)error { - return [self initWithClientId:clientId - tag:nil - error:error]; + return [self initWithClientId:clientId tag:nil error:error]; +} + +- (instancetype)initWithClientId:(NSString *)clientId + option:(LCIMClientOption *)option + error:(NSError *__autoreleasing _Nullable *)error +{ + return [self initWithClientId:clientId tag:nil option:option error:error]; +} + +- (instancetype)initWithClientId:(NSString *)clientId + tag:(NSString *)tag + error:(NSError *__autoreleasing _Nullable *)error +{ + return [self initWithClientId:clientId tag:tag option:nil error:error]; } - (instancetype)initWithClientId:(NSString *)clientId tag:(NSString *)tag + option:(LCIMClientOption *)option error:(NSError *__autoreleasing _Nullable *)error { - return [self initWithClientId:clientId - tag:tag - installation:[LCInstallation defaultInstallation] - error:error]; + LCInstallation *installation = [LCInstallation defaultInstallation]; + return [self initWithClientId:clientId tag:tag option:option installation:installation error:error]; } - (instancetype)initWithUser:(LCUser *)user error:(NSError *__autoreleasing _Nullable *)error { - return [self initWithUser:user - tag:nil - error:error]; + return [self initWithUser:user tag:nil error:error]; +} + +- (instancetype)initWithUser:(LCUser *)user + option:(LCIMClientOption *)option + error:(NSError *__autoreleasing _Nullable *)error +{ + return [self initWithUser:user tag:nil option:option error:error]; } - (instancetype)initWithUser:(LCUser *)user tag:(NSString *)tag error:(NSError *__autoreleasing _Nullable *)error { - return [self initWithUser:user - tag:tag - installation:[LCInstallation defaultInstallation] - error:error]; + return [self initWithUser:user tag:tag option:nil error:error]; +} + +- (instancetype)initWithUser:(LCUser *)user + tag:(NSString *)tag + option:(LCIMClientOption *)option + error:(NSError *__autoreleasing _Nullable *)error +{ + LCInstallation *installation = [LCInstallation defaultInstallation]; + return [self initWithUser:user tag:tag option:option installation:installation error:error]; } - (instancetype)initWithClientId:(NSString *)clientId tag:(NSString *)tag + option:(LCIMClientOption *)option installation:(LCInstallation *)installation error:(NSError *__autoreleasing _Nullable *)error { @@ -117,6 +144,7 @@ - (instancetype)initWithClientId:(NSString *)clientId if (self) { NSError *err = [self doInitializationWithClientId:clientId tag:tag + option:option installation:installation]; if (err) { if (error) { @@ -130,6 +158,7 @@ - (instancetype)initWithClientId:(NSString *)clientId - (instancetype)initWithUser:(LCUser *)user tag:(NSString *)tag + option:(LCIMClientOption *)option installation:(LCInstallation *)installation error:(NSError *__autoreleasing _Nullable *)error { @@ -138,6 +167,7 @@ - (instancetype)initWithUser:(LCUser *)user _user = user; NSError *err = [self doInitializationWithClientId:user.objectId tag:tag + option:option installation:installation]; if (err) { if (error) { @@ -151,6 +181,7 @@ - (instancetype)initWithUser:(LCUser *)user - (NSError *)doInitializationWithClientId:(NSString *)clientId tag:(NSString *)tag + option:(LCIMClientOption *)option installation:(LCInstallation *)installation { if (!clientId || @@ -212,14 +243,17 @@ - (NSError *)doInitializationWithClientId:(NSString *)clientId delegate:self queue:_internalSerialQueue]; _conversationManager = [[LCIMClientInternalConversationManager alloc] initWithClient:self]; - _installation = installation; - _currentDeviceToken = installation.deviceToken; - [installation addObserver:self - forKeyPath:keyPath(installation, deviceToken) - options:(NSKeyValueObservingOptionNew | - NSKeyValueObservingOptionOld | - NSKeyValueObservingOptionInitial) - context:(__bridge void *)(self)]; + BOOL isAutoBindingInstallationEnabled = (option ? !option.isAutoBindingInstallationDisabled : true); + if (isAutoBindingInstallationEnabled) { + _installation = installation; + _currentDeviceToken = installation.deviceToken; + [installation addObserver:self + forKeyPath:keyPath(installation, deviceToken) + options:(NSKeyValueObservingOptionNew | + NSKeyValueObservingOptionOld | + NSKeyValueObservingOptionInitial) + context:(__bridge void *)(self)]; + } _conversationCache = ({ LCIMConversationCache *cache = [[LCIMConversationCache alloc] initWithClientId:_clientId]; cache.client = self; @@ -1815,7 +1849,8 @@ - (void)removeAllConversationsInMemoryWith:(void (^)(void))callback - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if (context == (__bridge void *)(self)) { - if ([keyPath isEqualToString:keyPath(self.installation, deviceToken)] && + if (self.installation && + [keyPath isEqualToString:keyPath(self.installation, deviceToken)] && object == self.installation) { NSString *oldToken = [NSString _lc_decoding:change key:NSKeyValueChangeOldKey]; NSString *newToken = [NSString _lc_decoding:change key:NSKeyValueChangeNewKey]; diff --git a/AVOS/Sources/Realtime/IM/Client/LCIMClient_Internal.h b/AVOS/Sources/Realtime/IM/Client/LCIMClient_Internal.h index 0c91dfaf..746fcdcb 100644 --- a/AVOS/Sources/Realtime/IM/Client/LCIMClient_Internal.h +++ b/AVOS/Sources/Realtime/IM/Client/LCIMClient_Internal.h @@ -57,11 +57,13 @@ void assertContextOfQueue(dispatch_queue_t queue, BOOL isRunIn); - (instancetype)initWithClientId:(NSString *)clientId tag:(NSString *)tag + option:(LCIMClientOption *)option installation:(LCInstallation *)installation error:(NSError * __autoreleasing *)error; - (instancetype)initWithUser:(LCUser *)user tag:(NSString *)tag + option:(LCIMClientOption *)option installation:(LCInstallation *)installation error:(NSError * __autoreleasing *)error;