From 1d96d57aabe808c10c37e0b6e1b85511ee3e68b5 Mon Sep 17 00:00:00 2001 From: NidhiDixit09 <93544270+NidhiDixit09@users.noreply.github.com> Date: Tue, 17 Feb 2026 14:40:07 -0800 Subject: [PATCH 1/3] Removed Auto Initialization Added API - `- (void)setConsumerProtectionAttributionLevel:(BranchAttributionLevel)level resetSession:(BOOL)resetSession` to provide an option to disable resetting session. Remove silent SDK initialization - initSafetyCheck removed.Now APIs will return or log BNCInitError error. Added @synchronized(self) around all 5 init status checks to ensure it waits for any in-progress initSession code (which also uses @synchronized(self)) to finish and update the status before evaluating. --- Sources/BranchSDK/Branch.m | 75 ++++++++++++++++++++------ Sources/BranchSDK/Public/Branch.h | 9 ++++ Sources/BranchSDK/Public/BranchEvent.h | 10 ++-- 3 files changed, 73 insertions(+), 21 deletions(-) diff --git a/Sources/BranchSDK/Branch.m b/Sources/BranchSDK/Branch.m index df494708c..f2fead84a 100644 --- a/Sources/BranchSDK/Branch.m +++ b/Sources/BranchSDK/Branch.m @@ -690,6 +690,10 @@ + (void)setAnonID:(NSString *)anonID { } - (void)setConsumerProtectionAttributionLevel:(BranchAttributionLevel)level { + [self setConsumerProtectionAttributionLevel:level resetSession:YES]; +} + +- (void)setConsumerProtectionAttributionLevel:(BranchAttributionLevel)level resetSession:(BOOL)resetSession { self.preferenceHelper.attributionLevel = level; [[BranchLogger shared] logVerbose:[NSString stringWithFormat:@"Setting Consumer Protection Attribution Level to %@", level] error:nil]; @@ -720,8 +724,10 @@ - (void)setConsumerProtectionAttributionLevel:(BranchAttributionLevel)level { // Set the flag: [BNCPreferenceHelper sharedInstance].trackingDisabled = NO; - // Initialize a Branch session: - [[Branch getInstance] initUserSessionAndCallCallback:NO sceneIdentifier:nil urlString:nil reset:true]; + if (resetSession) { + // Initialize a Branch session: + [[Branch getInstance] initUserSessionAndCallCallback:NO sceneIdentifier:nil urlString:nil reset:true]; + } } } @@ -1220,7 +1226,16 @@ - (void)logoutWithCallback:(callbackWithStatus)callback { } - (void)sendServerRequest:(BNCServerRequest*)request { - [self initSafetyCheck]; + @synchronized (self) { + if (self.initializationStatus == BNCInitStatusUninitialized) { + NSError *error = [NSError branchErrorWithCode:BNCInitError]; + [[BranchLogger shared] logWarning:@"Branch SDK is not initialized, cannot send this request. Please intialize session before calling this API." error:error]; + BNCPerformBlockOnMainThreadSync(^{ + [[BNCCallbackMap shared] callCompletionForRequest:request withSuccessStatus:NO error:error]; + }); + return; + } + } dispatch_async(self.isolationQueue, ^(){ [self.requestQueue enqueue:request]; [self processNextQueueItem]; @@ -1298,7 +1313,14 @@ - (BranchLinkProperties *)getLatestReferringBranchLinkProperties { #pragma mark - Query methods - (void)lastAttributedTouchDataWithAttributionWindow:(NSInteger)window completion:(void(^) (BranchLastAttributedTouchData * _Nullable latd, NSError * _Nullable error))completion { - [self initSafetyCheck]; + @synchronized (self) { + if (self.initializationStatus == BNCInitStatusUninitialized) { + NSError *error = [NSError branchErrorWithCode:BNCInitError]; + [[BranchLogger shared] logWarning:@"Branch SDK is not initialized, cannot request LATD. Please intialize session before calling this API." error:error]; + if (completion) { completion(nil, error); } + return; + } + } dispatch_async(self.isolationQueue, ^(){ [BranchLastAttributedTouchData requestLastTouchAttributedData:self.serverInterface key:self.class.branchKey attributionWindow:window completion:completion]; }); @@ -1419,7 +1441,16 @@ - (void)getShortUrlWithParams:(NSDictionary *)params andTags:(NSArray *)tags and } - (void)getSpotlightUrlWithParams:(NSDictionary *)params callback:(callbackWithParams)callback { - [self initSafetyCheck]; + @synchronized (self) { + if (self.initializationStatus == BNCInitStatusUninitialized) { + NSError *error = [NSError branchErrorWithCode:BNCInitError]; + [[BranchLogger shared] logWarning:@"Branch SDK is not initialized, cannot create Spotlight URL. Please intialize session before calling this API." error:error]; + BNCPerformBlockOnMainThreadSync(^{ + if (callback) { callback(nil, error); } + }); + return; + } + } dispatch_async(self.isolationQueue, ^(){ BranchSpotlightUrlRequest *req = [[BranchSpotlightUrlRequest alloc] initWithParams:params callback:callback]; [self.requestQueue enqueue:req]; @@ -1683,7 +1714,18 @@ - (void)generateShortUrl:(NSArray *)tags andCampaign:campaign andParams:(NSDictionary *)params andCallback:(callbackWithUrl)callback { - [self initSafetyCheck]; + @synchronized (self) { + if (self.initializationStatus == BNCInitStatusUninitialized) { + NSError *error = [NSError branchErrorWithCode:BNCInitError]; + [[BranchLogger shared] logWarning:@"Branch SDK is not initialized, cannot generate short URL. Please intialize session before calling this API." error:error]; + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, error); + }); + } + return; + } + } dispatch_async(self.isolationQueue, ^(){ BNCLinkData *linkData = [self prepareLinkDataFor:tags andAlias:alias @@ -1891,7 +1933,18 @@ - (BNCLinkData *)prepareLinkDataFor:(NSArray *)tags #pragma mark - BranchUniversalObject methods - (void)registerViewWithParams:(NSDictionary *)params andCallback:(callbackWithParams)callback { - [self initSafetyCheck]; + @synchronized (self) { + if (self.initializationStatus == BNCInitStatusUninitialized) { + NSError *error = [NSError branchErrorWithCode:BNCInitError]; + [[BranchLogger shared] logWarning:@"Branch SDK is not initialized, cannot register view. Please intialize session before calling this API." error:error]; + if (callback) { + dispatch_async(dispatch_get_main_queue(), ^{ + callback(nil, error); + }); + } + return; + } + } dispatch_async(self.isolationQueue, ^(){ BranchUniversalObject *buo = [[BranchUniversalObject alloc] init]; buo.contentMetadata.customMetadata = (id) params; @@ -2151,14 +2204,6 @@ - (void)notifyNativeToInit { self.cachedInitBlock = nil; } -// SDK-631 Workaround to maintain existing error handling behavior. -// Some methods require init before they are called. Instead of returning an error, we try to fix the situation by calling init ourselves. -- (void)initSafetyCheck { - if (self.initializationStatus == BNCInitStatusUninitialized) { - [[BranchLogger shared] logDebug:@"Branch avoided an error by preemptively initializing." error:nil]; - [self initUserSessionAndCallCallback:NO sceneIdentifier:nil urlString:nil reset:NO]; - } -} - (void)initUserSessionAndCallCallback:(BOOL)callCallback sceneIdentifier:(NSString *)sceneIdentifier urlString:(NSString *)urlString reset:(BOOL)reset { diff --git a/Sources/BranchSDK/Public/Branch.h b/Sources/BranchSDK/Public/Branch.h index 9c9db93b2..017e745e4 100644 --- a/Sources/BranchSDK/Public/Branch.h +++ b/Sources/BranchSDK/Public/Branch.h @@ -941,6 +941,15 @@ extern BranchAttributionLevel const BranchAttributionLevelNone; */ - (void)setConsumerProtectionAttributionLevel:(BranchAttributionLevel)level; +/** + Sets the consumer protection attribution level with an option to reset the session. + + @param level The desired consumer protection attribution level, represented by the BranchAttributionLevel enum (Full, Reduced, Minimal, None). + @param resetSession If YES, a new session will be initialized when transitioning from BranchAttributionLevelNone to other higher levels. + If NO, the session will not be re-initialized automatically when transitioning from BranchAttributionLevelNone to other higher levels. + */ +- (void)setConsumerProtectionAttributionLevel:(BranchAttributionLevel)level resetSession:(BOOL)resetSession; + #pragma mark - Session Item methods diff --git a/Sources/BranchSDK/Public/BranchEvent.h b/Sources/BranchSDK/Public/BranchEvent.h index 1022f7599..5cdb8f076 100644 --- a/Sources/BranchSDK/Public/BranchEvent.h +++ b/Sources/BranchSDK/Public/BranchEvent.h @@ -97,20 +97,18 @@ typedef NS_ENUM(NSInteger, BranchEventAdType) { /** Logs the event on the Branch server. This version will callback on success/failure. - + This method should only be invoked after initSession. - If it is invoked before, then we will silently initialize the SDK before the callback has been set, in order to carry out this method's required task. - As a result, you may experience issues where the initSession callback does not fire. Again, the solution to this issue is to only invoke this method after you have invoked initSession. + If invoked before initSession, the event will be dropped and a BNCInitError will be returned. */ - (void)logEventWithCompletion:(void (^_Nullable)(BOOL success, NSError * _Nullable error))completion; /** Logs the event on the Branch server. This version automatically caches and retries as necessary. - + This method should only be invoked after initSession. - If it is invoked before, then we will silently initialize the SDK before the callback has been set, in order to carry out this method's required task. - As a result, you may experience issues where the initSession callback does not fire. Again, the solution to this issue is to only invoke this method after you have invoked initSession. + If invoked before initSession, the event will be dropped. */ - (void)logEvent; From 4b42bfa06d4e44a8f564d6e936328a12d24b092f Mon Sep 17 00:00:00 2001 From: NidhiDixit09 <93544270+NidhiDixit09@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:45:29 -0800 Subject: [PATCH 2/3] Moved callback to main thread asynchronously. --- Sources/BranchSDK/Branch.m | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Sources/BranchSDK/Branch.m b/Sources/BranchSDK/Branch.m index f2fead84a..b9686e12b 100644 --- a/Sources/BranchSDK/Branch.m +++ b/Sources/BranchSDK/Branch.m @@ -1230,9 +1230,11 @@ - (void)sendServerRequest:(BNCServerRequest*)request { if (self.initializationStatus == BNCInitStatusUninitialized) { NSError *error = [NSError branchErrorWithCode:BNCInitError]; [[BranchLogger shared] logWarning:@"Branch SDK is not initialized, cannot send this request. Please intialize session before calling this API." error:error]; - BNCPerformBlockOnMainThreadSync(^{ - [[BNCCallbackMap shared] callCompletionForRequest:request withSuccessStatus:NO error:error]; - }); + if ([[BNCCallbackMap shared] containsRequest:request]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[BNCCallbackMap shared] callCompletionForRequest:request withSuccessStatus:NO error:error]; + }); + } return; } } @@ -1317,7 +1319,9 @@ - (void)lastAttributedTouchDataWithAttributionWindow:(NSInteger)window completio if (self.initializationStatus == BNCInitStatusUninitialized) { NSError *error = [NSError branchErrorWithCode:BNCInitError]; [[BranchLogger shared] logWarning:@"Branch SDK is not initialized, cannot request LATD. Please intialize session before calling this API." error:error]; - if (completion) { completion(nil, error); } + dispatch_async(dispatch_get_main_queue(), ^{ + if (completion) { completion(nil, error); } + }); return; } } @@ -1445,7 +1449,7 @@ - (void)getSpotlightUrlWithParams:(NSDictionary *)params callback:(callbackWithP if (self.initializationStatus == BNCInitStatusUninitialized) { NSError *error = [NSError branchErrorWithCode:BNCInitError]; [[BranchLogger shared] logWarning:@"Branch SDK is not initialized, cannot create Spotlight URL. Please intialize session before calling this API." error:error]; - BNCPerformBlockOnMainThreadSync(^{ + dispatch_async(dispatch_get_main_queue(), ^{ if (callback) { callback(nil, error); } }); return; From ab57faafd46aa081e4698554b9fa364557ded500 Mon Sep 17 00:00:00 2001 From: NidhiDixit09 <93544270+NidhiDixit09@users.noreply.github.com> Date: Wed, 18 Feb 2026 08:37:06 -0800 Subject: [PATCH 3/3] Removed check, callCompletionForRequest has already that check. --- Sources/BranchSDK/Branch.m | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Sources/BranchSDK/Branch.m b/Sources/BranchSDK/Branch.m index b9686e12b..7c07940a7 100644 --- a/Sources/BranchSDK/Branch.m +++ b/Sources/BranchSDK/Branch.m @@ -1230,11 +1230,9 @@ - (void)sendServerRequest:(BNCServerRequest*)request { if (self.initializationStatus == BNCInitStatusUninitialized) { NSError *error = [NSError branchErrorWithCode:BNCInitError]; [[BranchLogger shared] logWarning:@"Branch SDK is not initialized, cannot send this request. Please intialize session before calling this API." error:error]; - if ([[BNCCallbackMap shared] containsRequest:request]) { - dispatch_async(dispatch_get_main_queue(), ^{ - [[BNCCallbackMap shared] callCompletionForRequest:request withSuccessStatus:NO error:error]; - }); - } + dispatch_async(dispatch_get_main_queue(), ^{ + [[BNCCallbackMap shared] callCompletionForRequest:request withSuccessStatus:NO error:error]; + }); return; } }