@@ -146,6 +146,10 @@ @interface Branch() <BranchDeepLinkingControllerCompletionDelegate> {
146146@property (assign , nonatomic ) BOOL delayForAppleAds;
147147@property (strong , nonatomic ) NSMutableArray *whiteListedSchemeList;
148148@property (strong , nonatomic ) BNCURLBlackList *URLBlackList;
149+
150+ // dedicated object for locking asyncRequestCount
151+ @property (strong , nonatomic , readwrite ) NSObject *asyncRequestCountLock;
152+
149153@end
150154
151155@implementation Branch
@@ -236,6 +240,8 @@ - (id)initWithInterface:(BNCServerInterface *)interface
236240 self = [super init ];
237241 if (!self) return self;
238242
243+ self.asyncRequestCountLock = [NSObject new ];
244+
239245 // Initialize instance variables
240246
241247 _serverInterface = interface;
@@ -249,7 +255,9 @@ - (id)initWithInterface:(BNCServerInterface *)interface
249255 _shouldCallSessionInitCallback = YES ;
250256 _processing_sema = dispatch_semaphore_create (1 );
251257 _networkCount = 0 ;
252- _asyncRequestCount = 0 ;
258+ @synchronized (self.asyncRequestCountLock ) {
259+ _asyncRequestCount = 0 ;
260+ }
253261 _deepLinkControllers = [[NSMutableDictionary alloc ] init ];
254262 _whiteListedSchemeList = [[NSMutableArray alloc ] init ];
255263 _useCookieBasedMatching = YES ;
@@ -649,20 +657,28 @@ - (void)initSessionWithLaunchOptions:(NSDictionary *)options
649657 if (![options.allKeys containsObject: UIApplicationLaunchOptionsURLKey] &&
650658 ![options.allKeys containsObject: UIApplicationLaunchOptionsUserActivityDictionaryKey]) {
651659
652- self.asyncRequestCount = 0 ;
660+ @synchronized (self.asyncRequestCountLock ) {
661+ self.asyncRequestCount = 0 ;
662+ }
653663
654664 // These methods will increment self.asyncRequestCount if they make an async call:
655665
666+ // load application data
667+ [self loadApplicationData ];
656668 // load user agent
657669 [self loadUserAgent ];
658670 // If Facebook SDK is present, call deferred app link check here which will later on call initUserSession
659671 [self checkFacebookAppLinks ];
660672 // If developer opted in, call deferred apple search attribution API here which will later on call initUserSession
661673 [self checkAppleSearchAdsAttribution ];
662674
663- if (self.asyncRequestCount == 0 ) {
664- // If we're not looking for App Links or Apple Search Ads, initialize
665- [self initUserSessionAndCallCallback: YES ];
675+ @synchronized (self.asyncRequestCountLock ) {
676+ if (self.asyncRequestCount == 0 ) {
677+ // If we're not looking for App Links or Apple Search Ads, initialize
678+ dispatch_async (dispatch_get_main_queue (), ^{
679+ [self initUserSessionAndCallCallback: YES ];
680+ });
681+ }
666682 }
667683 }
668684 // Handle case where there is Universal Link present
@@ -937,16 +953,38 @@ - (void)handlePushNotification:(NSDictionary *)userInfo {
937953}
938954
939955- (void )loadUserAgent {
940- self.asyncRequestCount ++;
956+ @synchronized (self.asyncRequestCountLock ) {
957+ self.asyncRequestCount ++;
958+ }
959+
941960 [[BNCUserAgentCollector instance ] loadUserAgentForSystemBuildVersion: [BNCDeviceInfo systemBuildVersion ] withCompletion: ^(NSString * _Nullable userAgent) {
942- self.asyncRequestCount --;
943- // If there's another async attribution check in flight, don't continue with init:
944- if (self.asyncRequestCount > 0 ) return ;
961+ @synchronized ( self.asyncRequestCountLock ) {
962+ self. asyncRequestCount --;
963+ if (self.asyncRequestCount > 0 ) return ;
945964
946- self.preferenceHelper .shouldWaitForInit = NO ;
947- dispatch_async (dispatch_get_main_queue (), ^{
948- [self initUserSessionAndCallCallback: (self .initializationStatus != BNCInitStatusInitialized)];
949- });
965+ self.preferenceHelper .shouldWaitForInit = NO ;
966+ dispatch_async (dispatch_get_main_queue (), ^{
967+ [self initUserSessionAndCallCallback: (self .initializationStatus != BNCInitStatusInitialized)];
968+ });
969+ }
970+ }];
971+ }
972+
973+ - (void )loadApplicationData {
974+ @synchronized (self.asyncRequestCountLock ) {
975+ self.asyncRequestCount ++;
976+ }
977+
978+ [BNCApplication loadCurrentApplicationWithCompletion: ^(BNCApplication *application) {
979+ @synchronized (self.asyncRequestCountLock ) {
980+ self.asyncRequestCount --;
981+ if (self.asyncRequestCount > 0 ) return ;
982+
983+ self.preferenceHelper .shouldWaitForInit = NO ;
984+ dispatch_async (dispatch_get_main_queue (), ^{
985+ [self initUserSessionAndCallCallback: (self .initializationStatus != BNCInitStatusInitialized)];
986+ });
987+ }
950988 }];
951989}
952990
@@ -989,8 +1027,10 @@ - (BOOL)checkAppleSearchAdsAttribution {
9891027
9901028 self.preferenceHelper .shouldWaitForInit = YES ;
9911029 self.preferenceHelper .checkedAppleSearchAdAttribution = YES ;
992- self.asyncRequestCount ++;
993-
1030+ @synchronized (self.asyncRequestCountLock ) {
1031+ self.asyncRequestCount ++;
1032+ }
1033+
9941034 NSDate *startDate = [NSDate date ];
9951035 _Atomic __block BOOL hasBeenCalled = NO ;
9961036 void (^__nullable completionBlock)(NSDictionary *attrDetails, NSError *error) =
@@ -1021,14 +1061,15 @@ - (BOOL)checkAppleSearchAdsAttribution {
10211061 BNCLogError (@" Error while getting Apple Search Ad attribution: %@ ." , error);
10221062 }
10231063
1024- self.asyncRequestCount --;
1025- // If there's another async attribution check in flight, don't continue with init:
1026- if (self.asyncRequestCount > 0 ) return ;
1064+ @synchronized ( self.asyncRequestCountLock ) {
1065+ self. asyncRequestCount --;
1066+ if (self.asyncRequestCount > 0 ) return ;
10271067
1028- self.preferenceHelper .shouldWaitForInit = NO ;
1029- dispatch_async (dispatch_get_main_queue (), ^{
1030- [self initUserSessionAndCallCallback: (self .initializationStatus != BNCInitStatusInitialized)];
1031- });
1068+ self.preferenceHelper .shouldWaitForInit = NO ;
1069+ dispatch_async (dispatch_get_main_queue (), ^{
1070+ [self initUserSessionAndCallCallback: (self .initializationStatus != BNCInitStatusInitialized)];
1071+ });
1072+ }
10321073 }
10331074 };
10341075
@@ -1058,17 +1099,21 @@ - (BOOL)checkFacebookAppLinks {
10581099
10591100 if ([self .FBSDKAppLinkUtility methodForSelector: fetchDeferredAppLink]) {
10601101 void (^__nullable completionBlock)(NSURL *appLink, NSError *error) = ^void (NSURL *__nullable appLink, NSError *__nullable error) {
1061- self.asyncRequestCount --;
1062-
1063- // if there's another async attribution check in flight, don't continue with init
1064- if (self.asyncRequestCount > 0 ) { return ; }
1102+ @synchronized (self.asyncRequestCountLock ) {
1103+ self.asyncRequestCount --;
10651104
1066- self.preferenceHelper .shouldWaitForInit = NO ;
1105+ if (self.asyncRequestCount > 0 ) { return ; }
1106+ self.preferenceHelper .shouldWaitForInit = NO ;
10671107
1068- [self handleDeepLink: appLink];
1108+ dispatch_async (dispatch_get_main_queue (), ^{
1109+ [self handleDeepLink: appLink];
1110+ });
1111+ }
10691112 };
10701113
1071- self.asyncRequestCount ++;
1114+ @synchronized (self.asyncRequestCountLock ) {
1115+ self.asyncRequestCount ++;
1116+ }
10721117 self.preferenceHelper .checkedFacebookAppLinks = YES ;
10731118 self.preferenceHelper .shouldWaitForInit = YES ;
10741119
0 commit comments