diff --git a/Framework/Info.plist b/Framework/Info.plist
index c548a727..b09c7d99 100644
--- a/Framework/Info.plist
+++ b/Framework/Info.plist
@@ -15,7 +15,7 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 5.8.6
+ 5.9.0
CFBundleSignature
????
CFBundleVersion
diff --git a/Qonversion.podspec b/Qonversion.podspec
index 5197e2c2..de387663 100644
--- a/Qonversion.podspec
+++ b/Qonversion.podspec
@@ -3,7 +3,7 @@ Pod::Spec.new do |s|
idfa_exclude_files = ['Sources/Qonversion/IDFA']
s.name = 'Qonversion'
s.swift_version = '5.5'
- s.version = '5.8.6'
+ s.version = '5.9.0'
s.summary = 'qonversion.io'
s.description = <<-DESC
Deep Analytics for iOS Subscriptions
diff --git a/Sources/Qonversion/Public/QONConfiguration.m b/Sources/Qonversion/Public/QONConfiguration.m
index fc2c3613..9f71dce4 100644
--- a/Sources/Qonversion/Public/QONConfiguration.m
+++ b/Sources/Qonversion/Public/QONConfiguration.m
@@ -9,7 +9,7 @@
#import "QONConfiguration.h"
#import "QNAPIConstants.h"
-static NSString *const kSDKVersion = @"5.8.6";
+static NSString *const kSDKVersion = @"5.9.0";
@interface QONConfiguration ()
diff --git a/Sources/Qonversion/Public/Qonversion.h b/Sources/Qonversion/Public/Qonversion.h
index 54c3872f..959fe78d 100644
--- a/Sources/Qonversion/Public/Qonversion.h
+++ b/Sources/Qonversion/Public/Qonversion.h
@@ -67,6 +67,14 @@ static NSString *const QonversionApiErrorDomain = @"com.qonversion.io.api";
*/
- (void)identify:(NSString *)userID;
+/**
+ Call this function to link a user to his unique ID in your system and share purchase data.
+
+ @param userID - unique user ID in your system
+ @param completion - completion block that will be called when response is received
+ */
+- (void)identify:(NSString *)userID completion:(QONUserInfoCompletionHandler)completion;
+
/**
Call this function to unlink a user from his unique ID in your system and his purchase data.
*/
diff --git a/Sources/Qonversion/Public/Qonversion.m b/Sources/Qonversion/Public/Qonversion.m
index 3fffd13a..c1112d9f 100644
--- a/Sources/Qonversion/Public/Qonversion.m
+++ b/Sources/Qonversion/Public/Qonversion.m
@@ -114,27 +114,31 @@ - (void)syncHistoricalData {
}
- (void)identify:(NSString *)userID {
- [[Qonversion sharedInstance].productCenterManager identify:userID];
+ [self.productCenterManager identify:userID completion:nil];
+}
+
+- (void)identify:(NSString *)userID completion:(QONUserInfoCompletionHandler)completion {
+ [self.productCenterManager identify:userID completion:completion];
}
- (void)logout {
- [[Qonversion sharedInstance].productCenterManager logout];
+ [self.productCenterManager logout];
}
- (void)presentCodeRedemptionSheet {
- [[Qonversion sharedInstance].productCenterManager presentCodeRedemptionSheet];
+ [self.productCenterManager presentCodeRedemptionSheet];
}
- (void)setEntitlementsUpdateListener:(id)delegate {
- [[Qonversion sharedInstance].productCenterManager setPurchasesDelegate:delegate];
+ [self.productCenterManager setPurchasesDelegate:delegate];
}
- (void)setPromoPurchasesDelegate:(id)delegate {
- [[Qonversion sharedInstance].productCenterManager setPromoPurchasesDelegate:delegate];
+ [self.productCenterManager setPromoPurchasesDelegate:delegate];
}
- (void)attribution:(NSDictionary *)data fromProvider:(QONAttributionProvider)provider {
- [[Qonversion sharedInstance].attributionManager addAttributionData:data fromProvider:provider];
+ [self.attributionManager addAttributionData:data fromProvider:provider];
}
- (void)setUserProperty:(QONUserPropertyKey)key value:(NSString *)value {
@@ -152,87 +156,87 @@ - (void)setUserProperty:(QONUserPropertyKey)key value:(NSString *)value {
}
- (void)setCustomUserProperty:(NSString *)property value:(NSString *)value {
- [[Qonversion sharedInstance].propertiesManager setUserProperty:property value:value];
+ [self.propertiesManager setUserProperty:property value:value];
}
- (void)userProperties:(QONUserPropertiesCompletionHandler)completion {
- [[Qonversion sharedInstance].propertiesManager getUserProperties:completion];
+ [self.propertiesManager getUserProperties:completion];
}
- (void)checkEntitlements:(QONEntitlementsCompletionHandler)completion {
- [[Qonversion sharedInstance].productCenterManager checkEntitlements:completion];
+ [self.productCenterManager checkEntitlements:completion];
}
- (void)purchaseProduct:(QONProduct *)product completion:(QONPurchaseCompletionHandler)completion {
- [[Qonversion sharedInstance].productCenterManager purchaseProduct:product completion:completion];
+ [self.productCenterManager purchaseProduct:product completion:completion];
}
- (void)purchase:(NSString *)productID completion:(QONPurchaseCompletionHandler)completion {
- [[Qonversion sharedInstance].productCenterManager purchase:productID completion:completion];
+ [self.productCenterManager purchase:productID completion:completion];
}
- (void)restore:(QNRestoreCompletionHandler)completion {
- [[Qonversion sharedInstance].productCenterManager restore:completion];
+ [self.productCenterManager restore:completion];
}
- (void)products:(QONProductsCompletionHandler)completion {
- return [[Qonversion sharedInstance].productCenterManager products:completion];
+ return [self.productCenterManager products:completion];
}
- (void)checkTrialIntroEligibility:(NSArray *)productIds completion:(QONEligibilityCompletionHandler)completion {
- [[Qonversion sharedInstance].productCenterManager checkTrialIntroEligibilityForProductIds:productIds completion:completion];
+ [self.productCenterManager checkTrialIntroEligibilityForProductIds:productIds completion:completion];
}
- (void)offerings:(QONOfferingsCompletionHandler)completion {
- return [[Qonversion sharedInstance].productCenterManager offerings:completion];
+ return [self.productCenterManager offerings:completion];
}
- (void)collectAppleSearchAdsAttribution {
- [[Qonversion sharedInstance].attributionManager addAppleSearchAttributionData];
+ [self.attributionManager addAppleSearchAttributionData];
}
- (void)userInfo:(QONUserInfoCompletionHandler)completion {
- [[[Qonversion sharedInstance] productCenterManager] userInfo:completion];
+ [[self productCenterManager] userInfo:completion];
}
- (void)remoteConfig:(QONRemoteConfigCompletionHandler)completion {
- [[[Qonversion sharedInstance] remoteConfigManager] obtainRemoteConfigWithContextKey:nil completion:completion];
+ [[self remoteConfigManager] obtainRemoteConfigWithContextKey:nil completion:completion];
}
- (void)remoteConfig:(NSString *)contextKey completion:(QONRemoteConfigCompletionHandler)completion {
- [[[Qonversion sharedInstance] remoteConfigManager] obtainRemoteConfigWithContextKey:contextKey completion:completion];
+ [[self remoteConfigManager] obtainRemoteConfigWithContextKey:contextKey completion:completion];
}
- (void)remoteConfigList:(NSArray *)contextKeys includeEmptyContextKey:(BOOL)includeEmptyContextKey completion:(QONRemoteConfigListCompletionHandler)completion {
- [[[Qonversion sharedInstance] remoteConfigManager] obtainRemoteConfigListWithContextKeys:contextKeys includeEmptyContextKey:includeEmptyContextKey completion:completion];
+ [[self remoteConfigManager] obtainRemoteConfigListWithContextKeys:contextKeys includeEmptyContextKey:includeEmptyContextKey completion:completion];
}
- (void)remoteConfigList:(QONRemoteConfigListCompletionHandler)completion {
- [[[Qonversion sharedInstance] remoteConfigManager] obtainRemoteConfigList:completion];
+ [[self remoteConfigManager] obtainRemoteConfigList:completion];
}
- (void)attachUserToExperiment:(NSString *)experimentId groupId:(NSString *)groupId completion:(QONExperimentAttachCompletionHandler)completion {
- [[[Qonversion sharedInstance] remoteConfigManager] attachUserToExperiment:experimentId groupId:groupId completion:completion];
+ [[self remoteConfigManager] attachUserToExperiment:experimentId groupId:groupId completion:completion];
}
- (void)detachUserFromExperiment:(NSString *)experimentId completion:(QONExperimentAttachCompletionHandler)completion {
- [[[Qonversion sharedInstance] remoteConfigManager] detachUserFromExperiment:experimentId completion:completion];
+ [[self remoteConfigManager] detachUserFromExperiment:experimentId completion:completion];
}
- (void)attachUserToRemoteConfiguration:(NSString *)remoteConfigurationId completion:(QONRemoteConfigurationAttachCompletionHandler)completion {
- [[[Qonversion sharedInstance] remoteConfigManager] attachUserToRemoteConfiguration:remoteConfigurationId completion:completion];
+ [[self remoteConfigManager] attachUserToRemoteConfiguration:remoteConfigurationId completion:completion];
}
- (void)detachUserFromRemoteConfiguration:(NSString *)remoteConfigurationId completion:(QONRemoteConfigurationAttachCompletionHandler)completion {
- [[[Qonversion sharedInstance] remoteConfigManager] detachUserFromRemoteConfiguration:remoteConfigurationId completion:completion];
+ [[self remoteConfigManager] detachUserFromRemoteConfiguration:remoteConfigurationId completion:completion];
}
- (void)handlePurchases:(NSArray *)purchasesInfo {
- [[Qonversion sharedInstance] handlePurchases:purchasesInfo completion:nil];
+ [self handlePurchases:purchasesInfo completion:nil];
}
- (void)handlePurchases:(NSArray *)purchasesInfo completion:(nullable QONDefaultCompletionHandler)completion {
- [[[Qonversion sharedInstance] productCenterManager] handlePurchases:purchasesInfo completion:completion];
+ [[self productCenterManager] handlePurchases:purchasesInfo completion:completion];
}
// MARK: - Private
@@ -264,7 +268,7 @@ - (instancetype)initWithCustomUserDefaults:(NSUserDefaults *)userDefaults {
- (void)collectAdvertisingId {
NSString *idfa = [QNDevice current].advertiserID;
- [[Qonversion sharedInstance] setUserProperty:QONUserPropertyKeyAdvertisingID value:idfa];
+ [self setUserProperty:QONUserPropertyKeyAdvertisingID value:idfa];
}
@end
diff --git a/Sources/Qonversion/Qonversion/Main/QNProductCenterManager/QNProductCenterManager.h b/Sources/Qonversion/Qonversion/Main/QNProductCenterManager/QNProductCenterManager.h
index 310d7bf3..d9743450 100644
--- a/Sources/Qonversion/Qonversion/Main/QNProductCenterManager/QNProductCenterManager.h
+++ b/Sources/Qonversion/Qonversion/Main/QNProductCenterManager/QNProductCenterManager.h
@@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
- (instancetype)initWithUserInfoService:(id)userInfoService identityManager:(id)identityManager localStorage:(id)localStorage;
- (BOOL)isUserStable;
-- (void)identify:(NSString *)userID;
+- (void)identify:(NSString *)userID completion:(nullable QONUserInfoCompletionHandler)completion;
- (void)logout;
- (void)setPurchasesDelegate:(id)delegate;
- (void)setPromoPurchasesDelegate:(id)delegate;
diff --git a/Sources/Qonversion/Qonversion/Main/QNProductCenterManager/QNProductCenterManager.m b/Sources/Qonversion/Qonversion/Main/QNProductCenterManager/QNProductCenterManager.m
index 1d58787a..e97bb882 100644
--- a/Sources/Qonversion/Qonversion/Main/QNProductCenterManager/QNProductCenterManager.m
+++ b/Sources/Qonversion/Qonversion/Main/QNProductCenterManager/QNProductCenterManager.m
@@ -40,7 +40,7 @@ @interface QNProductCenterManager()
@property (nonatomic, copy) NSArray *restoredTransactions;
-@property (nonatomic, strong) NSMutableDictionary *purchasingBlocks;
+@property (nonatomic, strong) NSMutableDictionary *purchasingBlocks;
@property (nonatomic, strong) NSMutableArray *restorePurchasesBlocks;
@property (nonatomic, strong) NSMutableArray *entitlementsBlocks;
@property (nonatomic, strong) NSMutableArray *productsBlocks;
@@ -62,6 +62,7 @@ @interface QNProductCenterManager()
@property (nonatomic, assign) BOOL identityInProgress;
@property (nonatomic, assign) BOOL unhandledLogoutAvailable;
@property (nonatomic, copy) NSString *pendingIdentityUserID;
+@property (nonatomic, strong) NSMutableDictionary *> *pendingIdentityBlocks;
@end
@@ -97,6 +98,7 @@ - (instancetype)initWithUserInfoService:(id)userInfo
_productsBlocks = [NSMutableArray new];
_offeringsBlocks = [NSMutableArray new];
_userInfoBlocks = [NSMutableArray new];
+ _pendingIdentityBlocks = [NSMutableDictionary new];
}
return self;
@@ -198,15 +200,19 @@ - (void)launchWithCompletion:(nullable QONLaunchCompletionHandler)completion {
}];
}
-- (void)identify:(NSString *)userID {
+- (void)identify:(NSString *)identityId completion:(nullable QONUserInfoCompletionHandler)completion {
self.unhandledLogoutAvailable = NO;
- NSString *currentIdentityID = [self.userInfoService obtainCustomIdentityUserID];
- if ([currentIdentityID isEqualToString:userID]) {
+ NSString *currentIdentityId = [self.userInfoService obtainCustomIdentityUserID];
+ if ([currentIdentityId isEqualToString:identityId]) {
+ if (completion) {
+ [self userInfo:completion];
+ }
return;
}
- self.pendingIdentityUserID = userID;
+ [self addIdentityCompletion:identityId completion:completion];
+ self.pendingIdentityUserID = identityId;
if (!self.launchingFinished || self.restoreInProgress) {
return;
}
@@ -221,39 +227,47 @@ - (void)identify:(NSString *)userID {
[weakSelf executeEntitlementsBlocksWithError:error];
[weakSelf.remoteConfigManager userChangingRequestFailedWithError:error];
} else {
- [weakSelf processIdentity:userID];
+ [weakSelf processIdentity:identityId];
}
}];
} else {
- [self processIdentity:userID];
+ [self processIdentity:identityId];
}
}
-- (void)processIdentity:(NSString *)userID {
+- (void)processIdentity:(NSString *)identityId {
NSString *currentUserID = [self.userInfoService obtainUserID];
__block __weak QNProductCenterManager *weakSelf = self;
- [self.identityManager identify:userID completion:^(NSString *result, NSError * _Nullable error) {
+ [self.identityManager identify:identityId completion:^(NSString *result, NSError * _Nullable error) {
weakSelf.identityInProgress = NO;
if (error) {
[weakSelf executeEntitlementsBlocksWithError:error];
[weakSelf.remoteConfigManager userChangingRequestFailedWithError:error];
+ [weakSelf fireIdentityError:error identityId:identityId];
return;
}
weakSelf.pendingIdentityUserID = nil;
- [weakSelf.userInfoService storeCustomIdentityUserID:userID];
+ [weakSelf.userInfoService storeCustomIdentityUserID:identityId];
if ([currentUserID isEqualToString:result]) {
[weakSelf handlePendingRequests:nil];
+ [weakSelf fireIdentitySuccess:identityId];
} else {
[[QNAPIClient shared] setUserID:result];
[weakSelf.remoteConfigManager userHasBeenChanged];
-
+
[weakSelf resetActualPermissionsCache];
- [weakSelf launchWithCompletion:nil];
+ [weakSelf launchWithCompletion:^(QONLaunchResult * _Nonnull result, NSError * _Nullable error) {
+ if (error) {
+ [weakSelf fireIdentityError:error identityId:identityId];
+ } else {
+ [weakSelf fireIdentitySuccess:identityId];
+ }
+ }];
}
}];
}
@@ -288,7 +302,7 @@ - (void)userInfo:(QONUserInfoCompletionHandler)completion {
}
[self actualizeUserInfo];
- completion(self.user, self.launchError);
+ run_block_on_main(completion, self.user, self.launchError);
}
- (void)presentCodeRedemptionSheet {
@@ -1189,7 +1203,7 @@ - (void)handlePendingRequests:(NSError *)lastError {
}
if (self.pendingIdentityUserID) {
- [self identify:self.pendingIdentityUserID];
+ [self identify:self.pendingIdentityUserID completion:nil];
} else if (self.unhandledLogoutAvailable) {
[self handleLogout];
} else {
@@ -1198,4 +1212,43 @@ - (void)handlePendingRequests:(NSError *)lastError {
}
}
+- (void)addIdentityCompletion:(NSString *)identityId completion:(nullable QONUserInfoCompletionHandler)completion {
+ if (!completion) {
+ return;
+ }
+
+ NSMutableArray *completions = self.pendingIdentityBlocks[identityId];
+ if (!completions) {
+ completions = [NSMutableArray new];
+ self.pendingIdentityBlocks[identityId] = completions;
+ }
+ [completions addObject:completion];
+}
+
+- (void)fireIdentitySuccess:(NSString *)identityId {
+ NSMutableArray *completions = self.pendingIdentityBlocks[identityId];
+ if (!completions) {
+ return;
+ }
+ self.pendingIdentityBlocks[identityId] = nil;
+
+ [self userInfo:^(QONUser * _Nullable user, NSError * _Nullable error) {
+ for (QONUserInfoCompletionHandler completion in completions) {
+ run_block_on_main(completion, user, error);
+ }
+ }];
+}
+
+- (void)fireIdentityError:(NSError * _Nullable)error identityId:(NSString *)identityId {
+ NSMutableArray *completions = self.pendingIdentityBlocks[identityId];
+ if (!completions) {
+ return;
+ }
+ self.pendingIdentityBlocks[identityId] = nil;
+ for (QONUserInfoCompletionHandler completion in completions) {
+ run_block_on_main(completion, nil, error);
+ }
+}
+
+
@end
diff --git a/fastlane/report.xml b/fastlane/report.xml
index b315de27..3a8f4d99 100644
--- a/fastlane/report.xml
+++ b/fastlane/report.xml
@@ -5,12 +5,12 @@
-
+
-
+