From 1fcb85c04075cc41b5e6cb12814eddcd67a73c00 Mon Sep 17 00:00:00 2001 From: BrandonStalnaker Date: Wed, 30 May 2018 10:17:18 -0400 Subject: [PATCH 01/21] Audit SDK Dependencies --- mParticle-Apple-SDK.podspec | 4 ++-- mParticle-Apple-SDK.xcodeproj/project.pbxproj | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/mParticle-Apple-SDK.podspec b/mParticle-Apple-SDK.podspec index f4f86ea7..e927203b 100644 --- a/mParticle-Apple-SDK.podspec +++ b/mParticle-Apple-SDK.podspec @@ -49,7 +49,7 @@ Pod::Spec.new do |s| ss.source_files = 'mParticle-Apple-SDK/**/*' ss.libraries = 'c++', 'sqlite3', 'z' - ss.ios.frameworks = 'Accounts', 'AdSupport', 'CoreGraphics', 'CoreLocation', 'CoreTelephony', 'Foundation', 'Security', 'Social', 'SystemConfiguration', 'UIKit' + ss.ios.frameworks = 'AdSupport', 'CoreGraphics', 'CoreLocation', 'CoreTelephony', 'Foundation', 'Security', 'SystemConfiguration', 'UIKit' ss.ios.weak_frameworks = 'iAd', 'UserNotifications' ss.tvos.frameworks = 'AdSupport', 'CoreGraphics', 'Foundation', 'Security', 'SystemConfiguration', 'UIKit' @@ -62,7 +62,7 @@ Pod::Spec.new do |s| ext.source_files = 'mParticle-Apple-SDK/**/*' ext.libraries = 'c++', 'sqlite3', 'z' - ext.ios.frameworks = 'Accounts', 'AdSupport', 'CoreGraphics', 'CoreLocation', 'CoreTelephony', 'Foundation', 'Security', 'Social', 'SystemConfiguration', 'UIKit' + ext.ios.frameworks = 'AdSupport', 'CoreGraphics', 'CoreLocation', 'CoreTelephony', 'Foundation', 'Security', 'SystemConfiguration', 'UIKit' ext.ios.weak_frameworks = 'iAd', 'UserNotifications' ext.tvos.frameworks = 'AdSupport', 'CoreGraphics', 'Foundation', 'Security', 'SystemConfiguration', 'UIKit' diff --git a/mParticle-Apple-SDK.xcodeproj/project.pbxproj b/mParticle-Apple-SDK.xcodeproj/project.pbxproj index f366e728..f9b33028 100644 --- a/mParticle-Apple-SDK.xcodeproj/project.pbxproj +++ b/mParticle-Apple-SDK.xcodeproj/project.pbxproj @@ -382,7 +382,6 @@ C9DD20631D8A142900D3ABBE /* MPIHasher.mm in Sources */ = {isa = PBXBuildFile; fileRef = C9DD1CFA1D8A112B00D3ABBE /* MPIHasher.mm */; }; C9DD20641D8A142900D3ABBE /* MPUserSegments.h in Headers */ = {isa = PBXBuildFile; fileRef = C9DD1CFB1D8A112B00D3ABBE /* MPUserSegments.h */; settings = {ATTRIBUTES = (Public, ); }; }; C9DD20651D8A142900D3ABBE /* MPUserSegments.m in Sources */ = {isa = PBXBuildFile; fileRef = C9DD1CFC1D8A112B00D3ABBE /* MPUserSegments.m */; }; - C9DD20681D8A146900D3ABBE /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9DD20671D8A146900D3ABBE /* Accounts.framework */; }; C9DD206A1D8A146F00D3ABBE /* AdSupport.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9DD20691D8A146F00D3ABBE /* AdSupport.framework */; }; C9DD206C1D8A147A00D3ABBE /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9DD206B1D8A147A00D3ABBE /* UIKit.framework */; }; C9DD206E1D8A148400D3ABBE /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9DD206D1D8A148400D3ABBE /* SystemConfiguration.framework */; }; @@ -700,7 +699,6 @@ C9DD1D371D8A112B00D3ABBE /* NSString+MPPercentEscape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+MPPercentEscape.h"; sourceTree = ""; }; C9DD1D381D8A112B00D3ABBE /* NSString+MPPercentEscape.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+MPPercentEscape.m"; sourceTree = ""; }; C9DD1DFF1D8A118400D3ABBE /* mParticle_Apple_SDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = mParticle_Apple_SDK.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - C9DD20671D8A146900D3ABBE /* Accounts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accounts.framework; path = System/Library/Frameworks/Accounts.framework; sourceTree = SDKROOT; }; C9DD20691D8A146F00D3ABBE /* AdSupport.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AdSupport.framework; path = System/Library/Frameworks/AdSupport.framework; sourceTree = SDKROOT; }; C9DD206B1D8A147A00D3ABBE /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; C9DD206D1D8A148400D3ABBE /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; @@ -839,7 +837,6 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C9DD20681D8A146900D3ABBE /* Accounts.framework in Frameworks */, C9DD206A1D8A146F00D3ABBE /* AdSupport.framework in Frameworks */, C9DD20801D8A14E200D3ABBE /* CoreGraphics.framework in Frameworks */, C9DD207E1D8A14D800D3ABBE /* CoreLocation.framework in Frameworks */, @@ -1228,7 +1225,6 @@ C9DD206D1D8A148400D3ABBE /* SystemConfiguration.framework */, C9DD206B1D8A147A00D3ABBE /* UIKit.framework */, C9DD20691D8A146F00D3ABBE /* AdSupport.framework */, - C9DD20671D8A146900D3ABBE /* Accounts.framework */, ); name = Frameworks; sourceTree = ""; From 097ffbddd7af96e864fe8171c1192ba045e58216 Mon Sep 17 00:00:00 2001 From: BrandonStalnaker Date: Tue, 22 May 2018 10:49:08 -0400 Subject: [PATCH 02/21] Fix App Extension Crash --- .../MPAppNotificationHandler.mm | 13 +- .../AppNotifications/MPSurrogateAppDelegate.m | 15 +- .../Data Model/MParticleUserNotification.h | 1 - .../Data Model/MParticleUserNotification.m | 5 +- .../Identity/MPIdentityApiRequest.m | 11 +- mParticle-Apple-SDK/Identity/MPIdentityDTO.m | 10 +- mParticle-Apple-SDK/MPBackendController.h | 4 +- mParticle-Apple-SDK/MPBackendController.mm | 131 +++++++------- mParticle-Apple-SDK/MPExceptionHandler.m | 13 +- .../Network/MPNetworkCommunication.mm | 114 ++++++------ .../Network/MPURLRequestBuilder.m | 12 +- .../Notifications/MPNotificationController.h | 3 +- .../Notifications/MPNotificationController.mm | 6 +- mParticle-Apple-SDK/Utils/MPApplication.h | 3 + mParticle-Apple-SDK/Utils/MPApplication.m | 63 ++++--- mParticle-Apple-SDK/Utils/MPCurrentState.m | 10 +- mParticle-Apple-SDK/Utils/MPDevice.m | 6 +- mParticle-Apple-SDK/Utils/MPMessageBuilder.mm | 14 +- mParticle-Apple-SDK/Utils/MPResponseConfig.m | 19 +- .../Utils/MPSearchAdsAttribution.m | 165 +++++++++--------- mParticle-Apple-SDK/Utils/MPStateMachine.h | 1 + mParticle-Apple-SDK/Utils/MPStateMachine.mm | 8 + mParticle-Apple-SDK/mParticle.h | 2 - mParticle-Apple-SDK/mParticle.m | 44 +++-- 24 files changed, 362 insertions(+), 311 deletions(-) diff --git a/mParticle-Apple-SDK/AppNotifications/MPAppNotificationHandler.mm b/mParticle-Apple-SDK/AppNotifications/MPAppNotificationHandler.mm index 6cbd4260..69eaf76e 100644 --- a/mParticle-Apple-SDK/AppNotifications/MPAppNotificationHandler.mm +++ b/mParticle-Apple-SDK/AppNotifications/MPAppNotificationHandler.mm @@ -92,9 +92,9 @@ - (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { return; } -#if !defined(MPARTICLE_APP_EXTENSIONS) - [MPNotificationController setDeviceToken:nil]; -#endif + if (![MPStateMachine isAppExtension]) { + [MPNotificationController setDeviceToken:nil]; + } SEL failedRegistrationSelector = @selector(failedToRegisterForUserNotifications:); @@ -116,9 +116,10 @@ - (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { return; } -#if !defined(MPARTICLE_APP_EXTENSIONS) - [MPNotificationController setDeviceToken:deviceToken]; -#endif + if (![MPStateMachine isAppExtension]) { + [MPNotificationController setDeviceToken:deviceToken]; + } + SEL deviceTokenSelector = @selector(setDeviceToken:); MPForwardQueueParameters *queueParameters = [[MPForwardQueueParameters alloc] init]; diff --git a/mParticle-Apple-SDK/AppNotifications/MPSurrogateAppDelegate.m b/mParticle-Apple-SDK/AppNotifications/MPSurrogateAppDelegate.m index 7144e982..7d82a374 100644 --- a/mParticle-Apple-SDK/AppNotifications/MPSurrogateAppDelegate.m +++ b/mParticle-Apple-SDK/AppNotifications/MPSurrogateAppDelegate.m @@ -2,6 +2,7 @@ #import "MPAppDelegateProxy.h" #import "MPNotificationController.h" #import "MPAppNotificationHandler.h" +#import "MPStateMachine.h" @implementation MPSurrogateAppDelegate @@ -11,9 +12,10 @@ @implementation MPSurrogateAppDelegate #pragma clang diagnostic ignored "-Wdeprecated-declarations" - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { NSDictionary *userInfo; -#if !defined(MPARTICLE_APP_EXTENSIONS) - userInfo = [MPNotificationController dictionaryFromLocalNotification:notification]; -#endif + if (![MPStateMachine isAppExtension]) { + userInfo = [MPNotificationController dictionaryFromLocalNotification:notification]; + } + if (userInfo) { [[MPAppNotificationHandler sharedInstance] receivedUserNotification:userInfo actionIdentifier:nil userNotificationMode:MPUserNotificationModeLocal]; } @@ -74,9 +76,10 @@ - (void)application:(UIApplication *)application didRegisterUserNotificationSett - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler { NSDictionary *userInfo; -#if !defined(MPARTICLE_APP_EXTENSIONS) - userInfo = [MPNotificationController dictionaryFromLocalNotification:notification]; -#endif + if (![MPStateMachine isAppExtension]) { + userInfo = [MPNotificationController dictionaryFromLocalNotification:notification]; + } + if (userInfo) { [[MPAppNotificationHandler sharedInstance] receivedUserNotification:userInfo actionIdentifier:identifier userNotificationMode:MPUserNotificationModeLocal]; } diff --git a/mParticle-Apple-SDK/Data Model/MParticleUserNotification.h b/mParticle-Apple-SDK/Data Model/MParticleUserNotification.h index c452e546..12381ab2 100644 --- a/mParticle-Apple-SDK/Data Model/MParticleUserNotification.h +++ b/mParticle-Apple-SDK/Data Model/MParticleUserNotification.h @@ -24,7 +24,6 @@ extern NSString * _Nonnull const kMPUserNotificationCategoryKey; #if TARGET_OS_IOS == 1 -NS_EXTENSION_UNAVAILABLE_IOS("") @interface MParticleUserNotification : MPDataModelAbstract @property (nonatomic, strong, nullable) NSString *actionIdentifier; diff --git a/mParticle-Apple-SDK/Data Model/MParticleUserNotification.m b/mParticle-Apple-SDK/Data Model/MParticleUserNotification.m index f7ba97a8..ac42c83a 100644 --- a/mParticle-Apple-SDK/Data Model/MParticleUserNotification.m +++ b/mParticle-Apple-SDK/Data Model/MParticleUserNotification.m @@ -1,4 +1,5 @@ #import "MParticleUserNotification.h" +#import "MPApplication.h" NSString *const kMPUserNotificationApsKey = @"aps"; NSString *const kMPUserNotificationAlertKey = @"alert"; @@ -45,10 +46,10 @@ - (instancetype)initWithDictionary:(NSDictionary *)notificationDictionary action #pragma clang diagnostic ignored "-Wdeprecated-declarations" __block UIUserNotificationSettings *userNotificationSettings = nil; if ([NSThread isMainThread]) { - userNotificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings]; + userNotificationSettings = [[MPApplication sharedUIApplication] currentUserNotificationSettings]; } else { dispatch_sync(dispatch_get_main_queue(), ^{ - userNotificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings]; + userNotificationSettings = [[MPApplication sharedUIApplication] currentUserNotificationSettings]; }); } diff --git a/mParticle-Apple-SDK/Identity/MPIdentityApiRequest.m b/mParticle-Apple-SDK/Identity/MPIdentityApiRequest.m index 05f4f4db..4d05d144 100644 --- a/mParticle-Apple-SDK/Identity/MPIdentityApiRequest.m +++ b/mParticle-Apple-SDK/Identity/MPIdentityApiRequest.m @@ -6,6 +6,7 @@ #import "MPDevice.h" #import "MPNotificationController.h" #import "MPIConstants.h" +#import "MPStateMachine.h" @implementation MPIdentityApiRequest @@ -114,12 +115,12 @@ + (MPIdentityApiRequest *)requestWithUser:(MParticleUser *) user { } #if TARGET_OS_IOS == 1 -#if !defined(MPARTICLE_APP_EXTENSIONS) - NSString *deviceToken = [[NSString alloc] initWithData:[MPNotificationController deviceToken] encoding:NSUTF8StringEncoding]; - if (deviceToken && [deviceToken length] > 0) { - knownIdentities[@"push_token"] = deviceToken; + if (![MPStateMachine isAppExtension]) { + NSString *deviceToken = [[NSString alloc] initWithData:[MPNotificationController deviceToken] encoding:NSUTF8StringEncoding]; + if (deviceToken && [deviceToken length] > 0) { + knownIdentities[@"push_token"] = deviceToken; + } } -#endif #endif return knownIdentities; diff --git a/mParticle-Apple-SDK/Identity/MPIdentityDTO.m b/mParticle-Apple-SDK/Identity/MPIdentityDTO.m index 369f9161..83b291e3 100644 --- a/mParticle-Apple-SDK/Identity/MPIdentityDTO.m +++ b/mParticle-Apple-SDK/Identity/MPIdentityDTO.m @@ -70,12 +70,12 @@ - (instancetype)initWithIdentityApiRequest:(MPIdentityApiRequest *)apiRequest { } #if TARGET_OS_IOS == 1 -#if !defined(MPARTICLE_APP_EXTENSIONS) - NSString *deviceToken = [[NSString alloc] initWithData:[MPNotificationController deviceToken] encoding:NSUTF8StringEncoding]; - if (deviceToken) { - _knownIdentities.pushToken = deviceToken; + if (![MPStateMachine isAppExtension]) { + NSString *deviceToken = [[NSString alloc] initWithData:[MPNotificationController deviceToken] encoding:NSUTF8StringEncoding]; + if (deviceToken) { + _knownIdentities.pushToken = deviceToken; + } } -#endif #endif } return self; diff --git a/mParticle-Apple-SDK/MPBackendController.h b/mParticle-Apple-SDK/MPBackendController.h index 2c47e1ad..fa1b8376 100644 --- a/mParticle-Apple-SDK/MPBackendController.h +++ b/mParticle-Apple-SDK/MPBackendController.h @@ -46,7 +46,7 @@ typedef NS_ENUM(NSUInteger, MPExecStatus) { #if TARGET_OS_IOS == 1 -@property (nonatomic, strong, nonnull) MPNotificationController *notificationController NS_EXTENSION_UNAVAILABLE_IOS(""); +@property (nonatomic, strong, nonnull) MPNotificationController *notificationController; #endif @property (nonatomic, weak, nullable) id delegate; @@ -88,7 +88,7 @@ typedef NS_ENUM(NSUInteger, MPExecStatus) { - (MPExecStatus)beginLocationTrackingWithAccuracy:(CLLocationAccuracy)accuracy distanceFilter:(CLLocationDistance)distance authorizationRequest:(MPLocationAuthorizationRequest)authorizationRequest; - (MPExecStatus)endLocationTracking; - (void)handleDeviceTokenNotification:(nonnull NSNotification *)notification; -- (void)receivedUserNotification:(nonnull MParticleUserNotification *)userNotification NS_EXTENSION_UNAVAILABLE_IOS(""); +- (void)receivedUserNotification:(nonnull MParticleUserNotification *)userNotification; #endif @end diff --git a/mParticle-Apple-SDK/MPBackendController.mm b/mParticle-Apple-SDK/MPBackendController.mm index b5ea0894..dbc17f83 100644 --- a/mParticle-Apple-SDK/MPBackendController.mm +++ b/mParticle-Apple-SDK/MPBackendController.mm @@ -256,11 +256,11 @@ - (MPSession *)session { } #pragma mark Private methods -- (void)beginBackgroundTask NS_EXTENSION_UNAVAILABLE_IOS(""){ +- (void)beginBackgroundTask { __weak MPBackendController *weakSelf = self; if (backendBackgroundTaskIdentifier == UIBackgroundTaskInvalid) { - backendBackgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + backendBackgroundTaskIdentifier = [[MPApplication sharedUIApplication] beginBackgroundTaskWithExpirationHandler:^{ MPILogDebug(@"SDK has ended background activity together with the app."); [MPStateMachine setRunningInBackground:NO]; @@ -288,9 +288,9 @@ - (void)beginBackgroundTask NS_EXTENSION_UNAVAILABLE_IOS(""){ } } -- (void)endBackgroundTask NS_EXTENSION_UNAVAILABLE_IOS(""){ +- (void)endBackgroundTask { if (backendBackgroundTaskIdentifier != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:backendBackgroundTaskIdentifier]; + [[MPApplication sharedUIApplication] endBackgroundTask:backendBackgroundTaskIdentifier]; backendBackgroundTaskIdentifier = UIBackgroundTaskInvalid; } } @@ -431,41 +431,41 @@ - (void)processDidFinishLaunching:(NSNotification *)notification { } #if TARGET_OS_IOS == 1 -#if !defined(MPARTICLE_APP_EXTENSIONS) - MParticleUserNotification *userNotification = nil; - NSDictionary *pushNotificationDictionary = userInfo[UIApplicationLaunchOptionsRemoteNotificationKey]; - - if (pushNotificationDictionary) { - NSError *error = nil; - NSData *remoteNotificationData = [NSJSONSerialization dataWithJSONObject:pushNotificationDictionary options:0 error:&error]; + if (![MPStateMachine isAppExtension]) { + MParticleUserNotification *userNotification = nil; + NSDictionary *pushNotificationDictionary = userInfo[UIApplicationLaunchOptionsRemoteNotificationKey]; - int64_t launchNotificationHash = 0; - if (!error && remoteNotificationData.length > 0) { - launchNotificationHash = mParticle::Hasher::hashFNV1a(static_cast([remoteNotificationData bytes]), static_cast([remoteNotificationData length])); - } - - if (launchNotificationHash != 0 && [MPNotificationController launchNotificationHash] != 0 && launchNotificationHash != [MPNotificationController launchNotificationHash]) { - astType = kMPASTForegroundKey; - userNotification = [self.notificationController newUserNotificationWithDictionary:pushNotificationDictionary - actionIdentifier:nil - state:kMPPushNotificationStateNotRunning]; + if (pushNotificationDictionary) { + NSError *error = nil; + NSData *remoteNotificationData = [NSJSONSerialization dataWithJSONObject:pushNotificationDictionary options:0 error:&error]; - if (userNotification.redactedUserNotificationString) { - messageInfo[kMPPushMessagePayloadKey] = userNotification.redactedUserNotificationString; + int64_t launchNotificationHash = 0; + if (!error && remoteNotificationData.length > 0) { + launchNotificationHash = mParticle::Hasher::hashFNV1a(static_cast([remoteNotificationData bytes]), static_cast([remoteNotificationData length])); } - if (_session) { - NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970]; - NSTimeInterval backgroundedTime = (currentTime - _session.endTime) > 0 ? (currentTime - _session.endTime) : 0; - sessionFinalized = backgroundedTime > self.sessionTimeout; + if (launchNotificationHash != 0 && [MPNotificationController launchNotificationHash] != 0 && launchNotificationHash != [MPNotificationController launchNotificationHash]) { + astType = kMPASTForegroundKey; + userNotification = [self.notificationController newUserNotificationWithDictionary:pushNotificationDictionary + actionIdentifier:nil + state:kMPPushNotificationStateNotRunning]; + + if (userNotification.redactedUserNotificationString) { + messageInfo[kMPPushMessagePayloadKey] = userNotification.redactedUserNotificationString; + } + + if (_session) { + NSTimeInterval currentTime = [[NSDate date] timeIntervalSince1970]; + NSTimeInterval backgroundedTime = (currentTime - _session.endTime) > 0 ? (currentTime - _session.endTime) : 0; + sessionFinalized = backgroundedTime > self.sessionTimeout; + } } } - } - - if (userNotification) { - [self receivedUserNotification:userNotification]; + + if (userNotification) { + [self receivedUserNotification:userNotification]; + } } -#endif #endif messageInfo[kMPAppStateTransitionType] = astType; @@ -569,15 +569,14 @@ - (void)processPendingUploads { }]; } -- (void)proxyOriginalAppDelegate NS_EXTENSION_UNAVAILABLE_IOS("") - { +- (void)proxyOriginalAppDelegate { if (originalAppDelegateProxied) { return; } originalAppDelegateProxied = YES; - UIApplication *application = [UIApplication sharedApplication]; + UIApplication *application = [MPApplication sharedUIApplication]; appDelegateProxy = [[MPAppDelegateProxy alloc] initWithOriginalAppDelegate:application.delegate]; application.delegate = appDelegateProxy; } @@ -857,13 +856,13 @@ - (void)handleApplicationDidEnterBackground:(NSNotification *)notification { timeAppWentToBackground = [[NSDate date] timeIntervalSince1970]; -#if !defined(MPARTICLE_APP_EXTENSIONS) - [self beginBackgroundTask]; - - if (MParticle.sharedInstance.automaticSessionTracking) { - [self beginBackgroundTimer]; + if (![MPStateMachine isAppExtension]) { + [self beginBackgroundTask]; + + if (MParticle.sharedInstance.automaticSessionTracking) { + [self beginBackgroundTimer]; + } } -#endif [self endUploadTimer]; @@ -887,15 +886,15 @@ - (void)handleApplicationDidEnterBackground:(NSNotification *)notification { [self.session suspendSession]; [self saveMessage:message updateSession:MParticle.sharedInstance.automaticSessionTracking]; -#if !defined(MPARTICLE_APP_EXTENSIONS) + if (![MPStateMachine isAppExtension]) { [self uploadDatabaseWithCompletionHandler:^{ if (!MParticle.sharedInstance.automaticSessionTracking) { [self endBackgroundTask]; } }]; -#else - [self endSession]; -#endif + } else { + [self endSession]; + } }); } @@ -908,9 +907,9 @@ - (void)handleApplicationWillEnterForeground:(NSNotification *)notification { [MPStateMachine setRunningInBackground:NO]; resignedActive = NO; -#if !defined(MPARTICLE_APP_EXTENSIONS) - [self endBackgroundTask]; -#endif + if (![MPStateMachine isAppExtension]) { + [self endBackgroundTask]; + } #if TARGET_OS_IOS == 1 if ([MPLocationManager trackingLocation] && ![MPStateMachine sharedInstance].locationManager.backgroundLocationTracking) { @@ -996,9 +995,9 @@ - (void)handleApplicationWillTerminate:(NSNotification *)notification { [persistence closeDatabase]; } -#if !defined(MPARTICLE_APP_EXTENSIONS) - [self endBackgroundTask]; -#endif + if (![MPStateMachine isAppExtension]) { + [self endBackgroundTask]; + } }); } @@ -1058,13 +1057,13 @@ - (void)handleApplicationWillResignActive:(NSNotification *)notification { } #pragma mark Timers -- (void)beginBackgroundTimer NS_EXTENSION_UNAVAILABLE_IOS(""){ +- (void)beginBackgroundTimer { __weak MPBackendController *weakSelf = self; backgroundSource = [self createSourceTimer:(MINIMUM_SESSION_TIMEOUT + 0.1) eventHandler:^{ - NSTimeInterval backgroundTimeRemaining = [[UIApplication sharedApplication] backgroundTimeRemaining]; + NSTimeInterval backgroundTimeRemaining = [[MPApplication sharedUIApplication] backgroundTimeRemaining]; dispatch_async([MParticle messageQueue], ^{ @@ -1821,11 +1820,11 @@ - (MPExecStatus)setSessionAttribute:(MPSession *)session key:(NSString *)key val } - (void)startWithKey:(NSString *)apiKey secret:(NSString *)secret firstRun:(BOOL)firstRun installationType:(MPInstallationType)installationType proxyAppDelegate:(BOOL)proxyAppDelegate startKitsAsync:(BOOL)startKitsAsync consentState:(MPConsentState *)consentState completionHandler:(dispatch_block_t)completionHandler { -#if !defined(MPARTICLE_APP_EXTENSIONS) - if (proxyAppDelegate) { - [self proxyOriginalAppDelegate]; + if (![MPStateMachine isAppExtension]) { + if (proxyAppDelegate) { + [self proxyOriginalAppDelegate]; + } } -#endif [MPPersistenceController setConsentState:consentState forMpid:[MPPersistenceController mpId]]; @@ -2197,16 +2196,16 @@ - (void)handleDeviceTokenNotification:(NSNotification *)notification { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" -#if !defined(MPARTICLE_APP_EXTENSIONS) - __block UIUserNotificationSettings *userNotificationSettings = nil; - dispatch_sync(dispatch_get_main_queue(), ^{ - userNotificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings]; - }); - - NSUInteger notificationTypes = userNotificationSettings.types; + if (![MPStateMachine isAppExtension]) { + __block UIUserNotificationSettings *userNotificationSettings = nil; + dispatch_sync(dispatch_get_main_queue(), ^{ + userNotificationSettings = [[MPApplication sharedUIApplication] currentUserNotificationSettings]; + }); + + NSUInteger notificationTypes = userNotificationSettings.types; #pragma clang diagnostic pop - messageInfo[kMPDeviceSupportedPushNotificationTypesKey] = @(notificationTypes); -#endif + messageInfo[kMPDeviceSupportedPushNotificationTypesKey] = @(notificationTypes); + } if ([MPStateMachine sharedInstance].deviceTokenType.length > 0) { messageInfo[kMPDeviceTokenTypeKey] = [MPStateMachine sharedInstance].deviceTokenType; diff --git a/mParticle-Apple-SDK/MPExceptionHandler.m b/mParticle-Apple-SDK/MPExceptionHandler.m index a3f48ca8..44139f0e 100644 --- a/mParticle-Apple-SDK/MPExceptionHandler.m +++ b/mParticle-Apple-SDK/MPExceptionHandler.m @@ -18,6 +18,7 @@ #import "MPPersistenceController.h" #import "MPILogger.h" #import "MPMessageBuilder.h" +#import "MPApplication.h" #if defined(MP_CRASH_REPORTER) && TARGET_OS_IOS == 1 #import @@ -166,12 +167,12 @@ - (id)topViewControllerForController:(UIViewController *)viewController { } - (NSString *)topmostContext { -#if !defined(MPARTICLE_APP_EXTENSIONS) - UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController; - id topmostContext = [self topViewControllerForController:rootViewController]; - NSString *topmostContextName = [[topmostContext class] description]; - return topmostContextName; -#endif + if (![MPStateMachine isAppExtension]) { + UIViewController *rootViewController = [MPApplication sharedUIApplication].keyWindow.rootViewController; + id topmostContext = [self topViewControllerForController:rootViewController]; + NSString *topmostContextName = [[topmostContext class] description]; + return topmostContextName; + } return @"extension_context"; } diff --git a/mParticle-Apple-SDK/Network/MPNetworkCommunication.mm b/mParticle-Apple-SDK/Network/MPNetworkCommunication.mm index 28051872..8b3a324e 100644 --- a/mParticle-Apple-SDK/Network/MPNetworkCommunication.mm +++ b/mParticle-Apple-SDK/Network/MPNetworkCommunication.mm @@ -297,15 +297,16 @@ - (void)requestConfig:(void(^)(BOOL success, NSDictionary *configurationDictiona MPILogVerbose(@"Starting config request"); NSTimeInterval start = [[NSDate date] timeIntervalSince1970]; -#if !defined(MPARTICLE_APP_EXTENSIONS) __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = UIBackgroundTaskInvalid; - backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; - backgroundTaskIdentifier = UIBackgroundTaskInvalid; - } - }]; -#endif + + if (![MPStateMachine isAppExtension]) { + backgroundTaskIdentifier = [[MPApplication sharedUIApplication] beginBackgroundTaskWithExpirationHandler:^{ + if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[MPApplication sharedUIApplication] endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } + }]; + } MPConnector *connector = [[MPConnector alloc] init]; NSString *const connectionId = [[NSUUID UUID] UUIDString]; @@ -321,12 +322,12 @@ - (void)requestConfig:(void(^)(BOOL success, NSDictionary *configurationDictiona return; } -#if !defined(MPARTICLE_APP_EXTENSIONS) - if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; - backgroundTaskIdentifier = UIBackgroundTaskInvalid; + if (![MPStateMachine isAppExtension]) { + if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[MPApplication sharedUIApplication] endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } } -#endif NSInteger responseCode = [httpResponse statusCode]; MPILogVerbose(@"Config Response Code: %ld, Execution Time: %.2fms", (long)responseCode, ([[NSDate date] timeIntervalSince1970] - start) * 1000.0); @@ -400,15 +401,16 @@ - (void)requestSegmentsWithTimeout:(NSTimeInterval)timeout completionHandler:(MP retrievingSegments = YES; -#if !defined(MPARTICLE_APP_EXTENSIONS) __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = UIBackgroundTaskInvalid; - backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; - backgroundTaskIdentifier = UIBackgroundTaskInvalid; - } - }]; -#endif + + if (![MPStateMachine isAppExtension]) { + backgroundTaskIdentifier = [[MPApplication sharedUIApplication] beginBackgroundTaskWithExpirationHandler:^{ + if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[MPApplication sharedUIApplication] endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } + }]; + } MPConnector *connector = [[MPConnector alloc] init]; @@ -425,12 +427,12 @@ - (void)requestSegmentsWithTimeout:(NSTimeInterval)timeout completionHandler:(MP return; } -#if !defined(MPARTICLE_APP_EXTENSIONS) - if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; - backgroundTaskIdentifier = UIBackgroundTaskInvalid; + if (![MPStateMachine isAppExtension]) { + if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[MPApplication sharedUIApplication] endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } } -#endif if (!data) { completionHandler(NO, nil, elapsedTime, nil); @@ -523,16 +525,16 @@ - (void)requestSegmentsWithTimeout:(NSTimeInterval)timeout completionHandler:(MP - (void)upload:(NSArray *)uploads index:(NSUInteger)index completionHandler:(MPUploadsCompletionHandler)completionHandler { __weak MPNetworkCommunication *weakSelf = self; -#if !defined(MPARTICLE_APP_EXTENSIONS) __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = UIBackgroundTaskInvalid; - backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; - backgroundTaskIdentifier = UIBackgroundTaskInvalid; - } - }]; -#endif + if (![MPStateMachine isAppExtension]) { + backgroundTaskIdentifier = [[MPApplication sharedUIApplication] beginBackgroundTaskWithExpirationHandler:^{ + if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[MPApplication sharedUIApplication] endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } + }]; + } MPUpload *upload = uploads[index]; NSString *uploadString = [upload serializedString]; @@ -567,12 +569,12 @@ - (void)upload:(NSArray *)uploads index:(NSUInteger)index completion return; } -#if !defined(MPARTICLE_APP_EXTENSIONS) - if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; - backgroundTaskIdentifier = UIBackgroundTaskInvalid; + if (![MPStateMachine isAppExtension]) { + if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[MPApplication sharedUIApplication] endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } } -#endif NSDictionary *responseDictionary = nil; MPNetworkResponseAction responseAction = MPNetworkResponseActionNone; @@ -646,21 +648,21 @@ - (void)identityApiRequestWithURL:(NSURL*)url identityRequest:(MPIdentityHTTPBas } __weak MPNetworkCommunication *weakSelf = self; -#if !defined(MPARTICLE_APP_EXTENSIONS) __block UIBackgroundTaskIdentifier backgroundTaskIdentifier = UIBackgroundTaskInvalid; - backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ - if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { - __strong MPNetworkCommunication *strongSelf = weakSelf; - if (strongSelf) { - strongSelf->identifying = NO; + if (![MPStateMachine isAppExtension]) { + backgroundTaskIdentifier = [[MPApplication sharedUIApplication] beginBackgroundTaskWithExpirationHandler:^{ + if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + __strong MPNetworkCommunication *strongSelf = weakSelf; + if (strongSelf) { + strongSelf->identifying = NO; + } + + [[MPApplication sharedUIApplication] endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; } - - [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; - backgroundTaskIdentifier = UIBackgroundTaskInvalid; - } - }]; -#endif + }]; + } MPConnector *connector = [[MPConnector alloc] init]; NSString *const connectionId = [[NSUUID UUID] UUIDString]; @@ -693,12 +695,12 @@ - (void)identityApiRequestWithURL:(NSURL*)url identityRequest:(MPIdentityHTTPBas return; } -#if !defined(MPARTICLE_APP_EXTENSIONS) - if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:backgroundTaskIdentifier]; - backgroundTaskIdentifier = UIBackgroundTaskInvalid; + if (![MPStateMachine isAppExtension]) { + if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { + [[MPApplication sharedUIApplication] endBackgroundTask:backgroundTaskIdentifier]; + backgroundTaskIdentifier = UIBackgroundTaskInvalid; + } } -#endif NSDictionary *responseDictionary = nil; NSString *responseString = nil; diff --git a/mParticle-Apple-SDK/Network/MPURLRequestBuilder.m b/mParticle-Apple-SDK/Network/MPURLRequestBuilder.m index 67b50365..16795409 100644 --- a/mParticle-Apple-SDK/Network/MPURLRequestBuilder.m +++ b/mParticle-Apple-SDK/Network/MPURLRequestBuilder.m @@ -7,6 +7,7 @@ #import "MPKitContainer.h" #import "MPExtensionProtocol.h" #import "MPILogger.h" +#import "MPApplication.h" static NSDateFormatter *RFC1123DateFormatter; static NSTimeInterval requestTimeout = 30.0; @@ -86,12 +87,13 @@ - (NSString *)userAgent { } dispatch_block_t getUserAgent = ^{ -#if !defined(MPARTICLE_APP_EXTENSIONS) - if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) { - mpUserAgent = defaultUserAgent; - return; + if (![MPStateMachine isAppExtension]) { + if ([MPApplication sharedUIApplication].applicationState == UIApplicationStateBackground) { + mpUserAgent = defaultUserAgent; + return; + } } -#endif + @try { UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectZero]; mpUserAgent = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; diff --git a/mParticle-Apple-SDK/Notifications/MPNotificationController.h b/mParticle-Apple-SDK/Notifications/MPNotificationController.h index 31da84eb..e6b111fb 100644 --- a/mParticle-Apple-SDK/Notifications/MPNotificationController.h +++ b/mParticle-Apple-SDK/Notifications/MPNotificationController.h @@ -3,7 +3,6 @@ #import "MParticleUserNotification.h" @protocol MPNotificationControllerDelegate; -NS_EXTENSION_UNAVAILABLE_IOS("") @interface MPNotificationController : NSObject #if TARGET_OS_IOS == 1 @@ -25,6 +24,6 @@ NS_EXTENSION_UNAVAILABLE_IOS("") @protocol MPNotificationControllerDelegate #if TARGET_OS_IOS == 1 -- (void)receivedUserNotification:(nonnull MParticleUserNotification *)userNotification NS_EXTENSION_UNAVAILABLE_IOS(""); +- (void)receivedUserNotification:(nonnull MParticleUserNotification *)userNotification; #endif @end diff --git a/mParticle-Apple-SDK/Notifications/MPNotificationController.mm b/mParticle-Apple-SDK/Notifications/MPNotificationController.mm index 4d8cddfa..d60f5b79 100644 --- a/mParticle-Apple-SDK/Notifications/MPNotificationController.mm +++ b/mParticle-Apple-SDK/Notifications/MPNotificationController.mm @@ -5,6 +5,8 @@ #include "MPHasher.h" #import "MParticle.h" #import "MPBackendController.h" +#import "MPApplication.h" +#import "MPStateMachine.h" @interface MPNotificationController() { BOOL appJustFinishedLaunching; @@ -95,7 +97,7 @@ - (BOOL)actionIdentifierBringsAppToTheForegound:(NSString *)actionIdentifier not #pragma clang diagnostic ignored "-Wdeprecated-declarations" UIUserNotificationSettings *userNotificationSettings = nil; if ([NSThread isMainThread]) { - userNotificationSettings = [[UIApplication sharedApplication] currentUserNotificationSettings]; + userNotificationSettings = [[MPApplication sharedUIApplication] currentUserNotificationSettings]; } if (!userNotificationSettings) { @@ -195,7 +197,7 @@ - (void)handleApplicationDidFinishLaunching:(NSNotification *)notification { notificationLaunchedApp = NO; } - if (userNotification && shouldDelegateReceivedRemoteNotification) { + if (userNotification && shouldDelegateReceivedRemoteNotification && ![MPStateMachine isAppExtension]) { [self.delegate receivedUserNotification:userNotification]; } } diff --git a/mParticle-Apple-SDK/Utils/MPApplication.h b/mParticle-Apple-SDK/Utils/MPApplication.h index 2de1a92a..238984e7 100644 --- a/mParticle-Apple-SDK/Utils/MPApplication.h +++ b/mParticle-Apple-SDK/Utils/MPApplication.h @@ -1,6 +1,8 @@ #import "MPIConstants.h" #import "MPEnums.h" +@class UIApplication; + extern NSString * _Nonnull const kMPApplicationInformationKey; @interface MPApplication : NSObject @@ -32,6 +34,7 @@ extern NSString * _Nonnull const kMPApplicationInformationKey; + (void)updateLastUseDate:(nonnull NSDate *)date; + (void)updateLaunchCountsAndDates; + (void)updateStoredVersionAndBuildNumbers; ++ (UIApplication *_Nullable)sharedUIApplication; - (nonnull NSDictionary *)dictionaryRepresentation; @end diff --git a/mParticle-Apple-SDK/Utils/MPApplication.m b/mParticle-Apple-SDK/Utils/MPApplication.m index 6e576d30..65c4df8b 100644 --- a/mParticle-Apple-SDK/Utils/MPApplication.m +++ b/mParticle-Apple-SDK/Utils/MPApplication.m @@ -258,51 +258,58 @@ - (NSString *)version { return bundleInfoDictionary[@"CFBundleShortVersionString"]; } ++ (UIApplication *)sharedUIApplication { + if ([[UIApplication class] respondsToSelector:@selector(sharedApplication)]) { + return [[UIApplication class] performSelector:@selector(sharedApplication)]; + } + return nil; +} + #if TARGET_OS_IOS == 1 - (NSNumber *)badgeNumber { -#if !defined(MPARTICLE_APP_EXTENSIONS) - __block NSInteger appBadgeNumber = 0; - if ([NSThread isMainThread]) { - appBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber; - } else { - dispatch_sync(dispatch_get_main_queue(), ^{ - appBadgeNumber = [UIApplication sharedApplication].applicationIconBadgeNumber; - }); + if (![MPStateMachine isAppExtension]) { + __block NSInteger appBadgeNumber = 0; + if ([NSThread isMainThread]) { + appBadgeNumber = [MPApplication sharedUIApplication].applicationIconBadgeNumber; + } else { + dispatch_sync(dispatch_get_main_queue(), ^{ + appBadgeNumber = [MPApplication sharedUIApplication].applicationIconBadgeNumber; + }); + } + NSNumber *badgeNumber = appBadgeNumber != 0 ? @(appBadgeNumber) : nil; + + return badgeNumber; } - NSNumber *badgeNumber = appBadgeNumber != 0 ? @(appBadgeNumber) : nil; - - return badgeNumber; -#endif return 0; } - (NSNumber *)remoteNotificationTypes { NSNumber *notificationTypes; -#if !defined(MPARTICLE_APP_EXTENSIONS) - UIApplication *app = [UIApplication sharedApplication]; - - if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) { + if (![MPStateMachine isAppExtension]) { + UIApplication *app = [[UIApplication class] performSelector:@selector(sharedApplication)]; + + if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - __block UIUserNotificationSettings *userNotificationSettings = nil; - if ([NSThread isMainThread]) { - userNotificationSettings = [app currentUserNotificationSettings]; - } else { - dispatch_sync(dispatch_get_main_queue(), ^{ + __block UIUserNotificationSettings *userNotificationSettings = nil; + if ([NSThread isMainThread]) { userNotificationSettings = [app currentUserNotificationSettings]; - }); - } - + } else { + dispatch_sync(dispatch_get_main_queue(), ^{ + userNotificationSettings = [app currentUserNotificationSettings]; + }); + } + #pragma clang diagnostic pop - notificationTypes = @(userNotificationSettings.types); - } else { + notificationTypes = @(userNotificationSettings.types); + } else { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - notificationTypes = @([app enabledRemoteNotificationTypes]); + notificationTypes = @([app enabledRemoteNotificationTypes]); #pragma clang diagnostic pop + } } -#endif return notificationTypes; } diff --git a/mParticle-Apple-SDK/Utils/MPCurrentState.m b/mParticle-Apple-SDK/Utils/MPCurrentState.m index 00a5afc3..520e572d 100644 --- a/mParticle-Apple-SDK/Utils/MPCurrentState.m +++ b/mParticle-Apple-SDK/Utils/MPCurrentState.m @@ -1,6 +1,7 @@ #import "MPCurrentState.h" #import #import "MPStateMachine.h" +#import "MPApplication.h" #if TARGET_OS_IOS == 1 #import @@ -189,12 +190,11 @@ - (NSNumber *)gpsState { } - (NSNumber *)statusBarOrientation { -#if !defined(MPARTICLE_APP_EXTENSIONS) - if ([NSThread isMainThread]) { - _statusBarOrientation = @([[UIApplication sharedApplication] statusBarOrientation]); + if (![MPStateMachine isAppExtension]) { + if ([NSThread isMainThread]) { + _statusBarOrientation = @([[MPApplication sharedUIApplication] statusBarOrientation]); + } } -#endif - return _statusBarOrientation; } #endif diff --git a/mParticle-Apple-SDK/Utils/MPDevice.m b/mParticle-Apple-SDK/Utils/MPDevice.m index 7f980025..3190028a 100644 --- a/mParticle-Apple-SDK/Utils/MPDevice.m +++ b/mParticle-Apple-SDK/Utils/MPDevice.m @@ -519,9 +519,9 @@ - (NSDictionary *)dictionaryRepresentation { } NSData *pushNotificationToken; -#if !defined(MPARTICLE_APP_EXTENSIONS) - pushNotificationToken = [MPNotificationController deviceToken]; -#endif + if (![MPStateMachine isAppExtension]) { + pushNotificationToken = [MPNotificationController deviceToken]; + } if (pushNotificationToken) { deviceDictionary[kMPDeviceTokenKey] = [NSString stringWithFormat:@"%@", pushNotificationToken]; } diff --git a/mParticle-Apple-SDK/Utils/MPMessageBuilder.mm b/mParticle-Apple-SDK/Utils/MPMessageBuilder.mm index 2f4a774b..b8130323 100644 --- a/mParticle-Apple-SDK/Utils/MPMessageBuilder.mm +++ b/mParticle-Apple-SDK/Utils/MPMessageBuilder.mm @@ -15,6 +15,7 @@ #import "MPUserAttributeChange.h" #import "MPUserIdentityChange.h" #import "MPPersistenceController.h" +#import "MPApplication.h" NSString *const launchInfoStringFormat = @"%@%@%@=%@"; NSString *const kMPHorizontalAccuracyKey = @"acc"; @@ -77,12 +78,13 @@ - (instancetype)initWithMessageType:(MPMessageType)messageType session:(MPSessio NSString *presentedViewControllerDescription = nil; NSNumber *mainThreadFlag; if ([NSThread isMainThread]) { -#if !defined(MPARTICLE_APP_EXTENSIONS) - UIViewController *presentedViewController = [UIApplication sharedApplication].keyWindow.rootViewController.presentedViewController; - presentedViewControllerDescription = presentedViewController ? [[presentedViewController class] description] : nil; -#else - presentedViewControllerDescription = @"extension_message"; -#endif + if (![MPStateMachine isAppExtension]) { + UIViewController *presentedViewController = [MPApplication sharedUIApplication].keyWindow.rootViewController.presentedViewController; + presentedViewControllerDescription = presentedViewController ? [[presentedViewController class] description] : nil; + } else { + presentedViewControllerDescription = @"extension_message"; + } + mainThreadFlag = @YES; } else { presentedViewControllerDescription = @"off_thread"; diff --git a/mParticle-Apple-SDK/Utils/MPResponseConfig.m b/mParticle-Apple-SDK/Utils/MPResponseConfig.m index e336650a..241f5d3d 100644 --- a/mParticle-Apple-SDK/Utils/MPResponseConfig.m +++ b/mParticle-Apple-SDK/Utils/MPResponseConfig.m @@ -6,6 +6,7 @@ #import "MPStateMachine.h" #import "MPIUserDefaults.h" #import "MPPersistenceController.h" +#import "MPApplication.h" #if TARGET_OS_IOS == 1 #import @@ -159,19 +160,19 @@ - (void)configureLocationTracking:(NSDictionary *)locationDictionary { - (void)configurePushNotifications:(NSDictionary *)pushNotificationDictionary { NSString *pushNotificationMode = pushNotificationDictionary[kMPRemoteConfigPushNotificationModeKey]; [MPStateMachine sharedInstance].pushNotificationMode = pushNotificationMode; -#if !defined(MPARTICLE_APP_EXTENSIONS) - UIApplication *app = [UIApplication sharedApplication]; - - if ([pushNotificationMode isEqualToString:kMPRemoteConfigForceTrue]) { - NSNumber *pushNotificationType = pushNotificationDictionary[kMPRemoteConfigPushNotificationTypeKey]; + if (![MPStateMachine isAppExtension]) { + UIApplication *app = [MPApplication sharedUIApplication]; + + if ([pushNotificationMode isEqualToString:kMPRemoteConfigForceTrue]) { + NSNumber *pushNotificationType = pushNotificationDictionary[kMPRemoteConfigPushNotificationTypeKey]; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - [app registerForRemoteNotificationTypes:[pushNotificationType integerValue]]; + [app registerForRemoteNotificationTypes:[pushNotificationType integerValue]]; #pragma clang diagnostic pop - } else if ([pushNotificationMode isEqualToString:kMPRemoteConfigForceFalse]) { - [app unregisterForRemoteNotifications]; + } else if ([pushNotificationMode isEqualToString:kMPRemoteConfigForceFalse]) { + [app unregisterForRemoteNotifications]; + } } -#endif } #endif diff --git a/mParticle-Apple-SDK/Utils/MPSearchAdsAttribution.m b/mParticle-Apple-SDK/Utils/MPSearchAdsAttribution.m index a2e2acf0..b29d3dee 100644 --- a/mParticle-Apple-SDK/Utils/MPSearchAdsAttribution.m +++ b/mParticle-Apple-SDK/Utils/MPSearchAdsAttribution.m @@ -1,5 +1,6 @@ #import "MPSearchAdsAttribution.h" #import "mParticle.h" +#import "MPStateMachine.h" #if TARGET_OS_IOS == 1 #import @@ -30,93 +31,97 @@ - (instancetype)init } - (void)requestAttributionDetailsWithBlock:(void (^ _Nonnull)(void))completionHandler { -#if TARGET_OS_IOS == 1 && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_9_3 && !defined(MPARTICLE_APP_EXTENSIONS) - Class MPClientClass = NSClassFromString(@"ADClient"); - if (!MPClientClass) { - completionHandler(); - return; - } +#if TARGET_OS_IOS == 1 && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_9_3 + if (![MPStateMachine isAppExtension]) { + Class MPClientClass = NSClassFromString(@"ADClient"); + if (!MPClientClass) { + completionHandler(); + return; + } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-performSelector-leaks" - SEL sharedClientSelector = NSSelectorFromString(@"sharedClient"); - if (![MPClientClass respondsToSelector:sharedClientSelector]) { - completionHandler(); - return; - } - - id MPClientSharedInstance = [MPClientClass performSelector:sharedClientSelector]; - if (!MPClientSharedInstance) { - completionHandler(); - return; - } - - SEL requestDetailsSelector = NSSelectorFromString(@"requestAttributionDetailsWithBlock:"); - if (![MPClientSharedInstance respondsToSelector:requestDetailsSelector]) { - completionHandler(); - return; - } - - __block BOOL called = NO; - void(^onceCompletionBlock)(void) = ^(){ - if (!called) { - called = YES; - dispatch_async(self->messageQueue, ^{ - completionHandler(); - }); + SEL sharedClientSelector = NSSelectorFromString(@"sharedClient"); + if (![MPClientClass respondsToSelector:sharedClientSelector]) { + completionHandler(); + return; } - }; - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - onceCompletionBlock(); - }); - - __weak MPSearchAdsAttribution *weakSelf = self; - int numRequests = 4; - __block int numRequestsCompleted = 0; - - void (^requestBlock)(void) = ^{ - if (!called) { - [MPClientSharedInstance performSelector:requestDetailsSelector withObject:^(NSDictionary *attributionDetails, NSError *error) { - ++numRequestsCompleted; - - __strong MPSearchAdsAttribution *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - if (!strongSelf.dictionary && attributionDetails && !error) { - NSDictionary* deepCopyDetails = nil; - @try { - deepCopyDetails = [NSKeyedUnarchiver unarchiveObjectWithData: - [NSKeyedArchiver archivedDataWithRootObject:attributionDetails]]; + + id MPClientSharedInstance = [MPClientClass performSelector:sharedClientSelector]; + if (!MPClientSharedInstance) { + completionHandler(); + return; + } + + SEL requestDetailsSelector = NSSelectorFromString(@"requestAttributionDetailsWithBlock:"); + if (![MPClientSharedInstance respondsToSelector:requestDetailsSelector]) { + completionHandler(); + return; + } + + __block BOOL called = NO; + void(^onceCompletionBlock)(void) = ^(){ + if (!called) { + called = YES; + dispatch_async(self->messageQueue, ^{ + completionHandler(); + }); + } + }; + + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(30 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ + onceCompletionBlock(); + }); + + __weak MPSearchAdsAttribution *weakSelf = self; + int numRequests = 4; + __block int numRequestsCompleted = 0; + + void (^requestBlock)(void) = ^{ + if (!called) { + [MPClientSharedInstance performSelector:requestDetailsSelector withObject:^(NSDictionary *attributionDetails, NSError *error) { + ++numRequestsCompleted; + + __strong MPSearchAdsAttribution *strongSelf = weakSelf; + if (!strongSelf) { + return; } - @catch (NSException *e) { - deepCopyDetails = [attributionDetails copy]; + + if (!strongSelf.dictionary && attributionDetails && !error) { + NSDictionary* deepCopyDetails = nil; + @try { + deepCopyDetails = [NSKeyedUnarchiver unarchiveObjectWithData: + [NSKeyedArchiver archivedDataWithRootObject:attributionDetails]]; + } + @catch (NSException *e) { + deepCopyDetails = [attributionDetails copy]; + } + + if (deepCopyDetails) { + strongSelf.dictionary = deepCopyDetails; + } + + onceCompletionBlock(); } - - if (deepCopyDetails) { - strongSelf.dictionary = deepCopyDetails; + else if (error.code == 1 /* ADClientErrorLimitAdTracking */) { + onceCompletionBlock(); } - - onceCompletionBlock(); - } - else if (error.code == 1 /* ADClientErrorLimitAdTracking */) { - onceCompletionBlock(); - } - else if (numRequestsCompleted >= numRequests) { - onceCompletionBlock(); - } - }]; - } - }; - - // Per Apple docs, "Handle any errors you receive and re-poll for data, if required" - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), requestBlock); - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), requestBlock); - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), requestBlock); - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(9 * NSEC_PER_SEC)), dispatch_get_main_queue(), requestBlock); - + else if (numRequestsCompleted >= numRequests) { + onceCompletionBlock(); + } + }]; + } + }; + + // Per Apple docs, "Handle any errors you receive and re-poll for data, if required" + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), requestBlock); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), requestBlock); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6 * NSEC_PER_SEC)), dispatch_get_main_queue(), requestBlock); + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(9 * NSEC_PER_SEC)), dispatch_get_main_queue(), requestBlock); + #pragma clang diagnostic pop + } else { + completionHandler(); + } #else completionHandler(); #endif diff --git a/mParticle-Apple-SDK/Utils/MPStateMachine.h b/mParticle-Apple-SDK/Utils/MPStateMachine.h index 01f81ab0..e5070617 100644 --- a/mParticle-Apple-SDK/Utils/MPStateMachine.h +++ b/mParticle-Apple-SDK/Utils/MPStateMachine.h @@ -61,6 +61,7 @@ typedef NS_ENUM(NSUInteger, MPConsoleLogging) { + (nullable NSString *)provisioningProfileString; + (BOOL)runningInBackground; + (void)setRunningInBackground:(BOOL)background; ++ (BOOL)isAppExtension; - (void)configureCustomModules:(nullable NSArray *)customModuleSettings; - (void)configureRampPercentage:(nullable NSNumber *)rampPercentage; - (void)configureTriggers:(nullable NSDictionary *)triggerDictionary; diff --git a/mParticle-Apple-SDK/Utils/MPStateMachine.mm b/mParticle-Apple-SDK/Utils/MPStateMachine.mm index fe50275a..6f472bff 100644 --- a/mParticle-Apple-SDK/Utils/MPStateMachine.mm +++ b/mParticle-Apple-SDK/Utils/MPStateMachine.mm @@ -346,6 +346,14 @@ + (void)setRunningInBackground:(BOOL)background { runningInBackground = background; } ++ (BOOL)isAppExtension { +#if TARGET_OS_IOS == 1 + return [[NSBundle mainBundle].bundlePath hasSuffix:@".appex"]; +#else + return NO; +#endif +} + #pragma mark Public accessors - (MPConsoleLogging)consoleLogging { if (_consoleLogging != MPConsoleLoggingAutoDetect) { diff --git a/mParticle-Apple-SDK/mParticle.h b/mParticle-Apple-SDK/mParticle.h index 6cdb887c..7c39dd0b 100644 --- a/mParticle-Apple-SDK/mParticle.h +++ b/mParticle-Apple-SDK/mParticle.h @@ -245,7 +245,6 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark - Application notifications #if TARGET_OS_IOS == 1 -#if !defined(MPARTICLE_APP_EXTENSIONS) /** Informs the mParticle SDK a local notification has been received. This method should be called only if proxiedAppDelegate is disabled. @param notification A local notification received by the app @@ -298,7 +297,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (void)handleActionWithIdentifier:(nullable NSString *)identifier forRemoteNotification:(nullable NSDictionary *)userInfo; #endif -#endif /** Informs the mParticle SDK the app has been asked to open a resource identified by a URL. diff --git a/mParticle-Apple-SDK/mParticle.m b/mParticle-Apple-SDK/mParticle.m index 829fe912..4b8d8e62 100644 --- a/mParticle-Apple-SDK/mParticle.m +++ b/mParticle-Apple-SDK/mParticle.m @@ -661,22 +661,29 @@ - (void)startWithOptions:(MParticleOptions *)options { #pragma mark Application notifications #if TARGET_OS_IOS == 1 -#if !defined(MPARTICLE_APP_EXTENSIONS) - (NSData *)pushNotificationToken { - return [MPNotificationController deviceToken]; + if (![MPStateMachine isAppExtension]) { + return [MPNotificationController deviceToken]; + } else { + return nil; + } } - (void)setPushNotificationToken:(NSData *)pushNotificationToken { - [MPNotificationController setDeviceToken:pushNotificationToken]; + if (![MPStateMachine isAppExtension]) { + [MPNotificationController setDeviceToken:pushNotificationToken]; + } } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - (void)didReceiveLocalNotification:(UILocalNotification *)notification { #pragma clang diagnostic pop - NSDictionary *userInfo = [MPNotificationController dictionaryFromLocalNotification:notification]; - if (userInfo && !self.proxiedAppDelegate) { - [[MPAppNotificationHandler sharedInstance] receivedUserNotification:userInfo actionIdentifier:nil userNotificationMode:MPUserNotificationModeLocal]; + if (![MPStateMachine isAppExtension]) { + NSDictionary *userInfo = [MPNotificationController dictionaryFromLocalNotification:notification]; + if (userInfo && !self.proxiedAppDelegate) { + [[MPAppNotificationHandler sharedInstance] receivedUserNotification:userInfo actionIdentifier:nil userNotificationMode:MPUserNotificationModeLocal]; + } } } @@ -685,7 +692,9 @@ - (void)didReceiveRemoteNotification:(NSDictionary *)userInfo { return; } - [[MPAppNotificationHandler sharedInstance] receivedUserNotification:userInfo actionIdentifier:nil userNotificationMode:MPUserNotificationModeRemote]; + if (![MPStateMachine isAppExtension]) { + [[MPAppNotificationHandler sharedInstance] receivedUserNotification:userInfo actionIdentifier:nil userNotificationMode:MPUserNotificationModeRemote]; + } } - (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { @@ -693,7 +702,9 @@ - (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { return; } - [[MPAppNotificationHandler sharedInstance] didFailToRegisterForRemoteNotificationsWithError:error]; + if (![MPStateMachine isAppExtension]) { + [[MPAppNotificationHandler sharedInstance] didFailToRegisterForRemoteNotificationsWithError:error]; + } } - (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { @@ -701,16 +712,20 @@ - (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { return; } - [[MPAppNotificationHandler sharedInstance] didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; + if (![MPStateMachine isAppExtension]) { + [[MPAppNotificationHandler sharedInstance] didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; + } } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - (void)handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification { #pragma clang diagnostic pop - NSDictionary *userInfo = [MPNotificationController dictionaryFromLocalNotification:notification]; - if (userInfo && !self.proxiedAppDelegate) { - [[MPAppNotificationHandler sharedInstance] receivedUserNotification:userInfo actionIdentifier:identifier userNotificationMode:MPUserNotificationModeLocal]; + if (![MPStateMachine isAppExtension]) { + NSDictionary *userInfo = [MPNotificationController dictionaryFromLocalNotification:notification]; + if (userInfo && !self.proxiedAppDelegate) { + [[MPAppNotificationHandler sharedInstance] receivedUserNotification:userInfo actionIdentifier:identifier userNotificationMode:MPUserNotificationModeLocal]; + } } } @@ -719,10 +734,11 @@ - (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification: return; } - [[MPAppNotificationHandler sharedInstance] handleActionWithIdentifier:identifier forRemoteNotification:userInfo]; + if (![MPStateMachine isAppExtension]) { + [[MPAppNotificationHandler sharedInstance] handleActionWithIdentifier:identifier forRemoteNotification:userInfo]; + } } #endif -#endif - (void)openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { if (_proxiedAppDelegate) { From cc6d0d936e22262b2873932f7261b95dacd7414a Mon Sep 17 00:00:00 2001 From: mParticle Automation Date: Wed, 6 Jun 2018 14:52:29 -0400 Subject: [PATCH 03/21] Update version to 7.3.10 --- Framework/Info.plist | 2 +- mParticle-Apple-SDK.podspec | 2 +- mParticle-Apple-SDK/MPIConstants.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Info.plist b/Framework/Info.plist index fb5730c4..1dbf5af5 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 7.3.9 + 7.3.10 CFBundleSignature ???? CFBundleVersion diff --git a/mParticle-Apple-SDK.podspec b/mParticle-Apple-SDK.podspec index e927203b..3d4e0518 100644 --- a/mParticle-Apple-SDK.podspec +++ b/mParticle-Apple-SDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "mParticle-Apple-SDK" - s.version = "7.3.9" + s.version = "7.3.10" s.summary = "mParticle Apple SDK." s.description = <<-DESC diff --git a/mParticle-Apple-SDK/MPIConstants.m b/mParticle-Apple-SDK/MPIConstants.m index ed71cf47..35a43361 100644 --- a/mParticle-Apple-SDK/MPIConstants.m +++ b/mParticle-Apple-SDK/MPIConstants.m @@ -1,7 +1,7 @@ #import "MPIConstants.h" // mParticle SDK Version -NSString *const kMParticleSDKVersion = @"7.3.9"; +NSString *const kMParticleSDKVersion = @"7.3.10"; // Message Type (dt) NSString *const kMPMessageTypeKey = @"dt"; From e4d6c20692e1eab1570829941a4d2e3f7f17bc14 Mon Sep 17 00:00:00 2001 From: Peter Jenkins Date: Fri, 8 Jun 2018 13:35:44 -0400 Subject: [PATCH 04/21] Fix deferred start kits when no identity handler --- mParticle-Apple-SDK/mParticle.m | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/mParticle-Apple-SDK/mParticle.m b/mParticle-Apple-SDK/mParticle.m index 4b8d8e62..91156946 100644 --- a/mParticle-Apple-SDK/mParticle.m +++ b/mParticle-Apple-SDK/mParticle.m @@ -599,19 +599,19 @@ - (void)startWithOptions:(MParticleOptions *)options { if (error) { MPILogError(@"Identify request failed with error: %@", error); } - if (options.onIdentifyComplete) { - - NSArray *deferredKitConfiguration = self.deferredKitConfiguration; + + NSArray *deferredKitConfiguration = self.deferredKitConfiguration; + + if (deferredKitConfiguration != nil && [deferredKitConfiguration isKindOfClass:[NSArray class]]) { - if (deferredKitConfiguration != nil && [deferredKitConfiguration isKindOfClass:[NSArray class]]) { - - dispatch_sync(dispatch_get_main_queue(), ^{ - [[MPKitContainer sharedInstance] configureKits:deferredKitConfiguration]; - weakSelf.deferredKitConfiguration = nil; - }); - - } + dispatch_sync(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] configureKits:deferredKitConfiguration]; + weakSelf.deferredKitConfiguration = nil; + }); + } + + if (options.onIdentifyComplete) { dispatch_async(dispatch_get_main_queue(), ^{ options.onIdentifyComplete(apiResult, error); }); From e5b36f4a3f924cb7008ebf2e4d93b6a804365a79 Mon Sep 17 00:00:00 2001 From: Peter Jenkins Date: Fri, 8 Jun 2018 13:44:28 -0400 Subject: [PATCH 05/21] Guard against starting kits on message queue --- mParticle-Apple-SDK/Kits/MPKitContainer.mm | 24 ++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/mParticle-Apple-SDK/Kits/MPKitContainer.mm b/mParticle-Apple-SDK/Kits/MPKitContainer.mm index a25212d4..a3507b32 100644 --- a/mParticle-Apple-SDK/Kits/MPKitContainer.mm +++ b/mParticle-Apple-SDK/Kits/MPKitContainer.mm @@ -445,15 +445,23 @@ - (void)startKitRegister:(nonnull id)kitRegister configu configuration = [self validateAndTransformToSafeConfiguration:configuration]; if (configuration) { - kitRegister.wrapperInstance = [[NSClassFromString(kitRegister.className) alloc] init]; - - MPKitAPI *kitApi = [[MPKitAPI alloc] initWithKitCode:kitRegister.code]; - if ([kitRegister.wrapperInstance respondsToSelector:@selector(setKitApi:)]) { - [kitRegister.wrapperInstance setKitApi:kitApi]; - } + dispatch_block_t kitBlock = ^{ + kitRegister.wrapperInstance = [[NSClassFromString(kitRegister.className) alloc] init]; + + MPKitAPI *kitApi = [[MPKitAPI alloc] initWithKitCode:kitRegister.code]; + if ([kitRegister.wrapperInstance respondsToSelector:@selector(setKitApi:)]) { + [kitRegister.wrapperInstance setKitApi:kitApi]; + } + + if ([kitRegister.wrapperInstance respondsToSelector:@selector(didFinishLaunchingWithConfiguration:)]) { + [kitRegister.wrapperInstance didFinishLaunchingWithConfiguration:configuration]; + } + }; - if ([kitRegister.wrapperInstance respondsToSelector:@selector(didFinishLaunchingWithConfiguration:)]) { - [kitRegister.wrapperInstance didFinishLaunchingWithConfiguration:configuration]; + if ([NSThread isMainThread]) { + kitBlock(); + } else { + dispatch_sync(dispatch_get_main_queue(), kitBlock); } } } From e933471ec443c02d82ee02de6305c676e3635991 Mon Sep 17 00:00:00 2001 From: Peter Jenkins Date: Fri, 8 Jun 2018 15:00:16 -0400 Subject: [PATCH 06/21] Only treat consent filters as present if non-empty --- mParticle-Apple-SDK/MPIConstants.h | 9 +++++++++ mParticle-Apple-SDK/Utils/MPResponseConfig.m | 14 +++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/mParticle-Apple-SDK/MPIConstants.h b/mParticle-Apple-SDK/MPIConstants.h index 46579043..2b63b0fc 100644 --- a/mParticle-Apple-SDK/MPIConstants.h +++ b/mParticle-Apple-SDK/MPIConstants.h @@ -11,6 +11,15 @@ #define STATE_MACHINE_DIRECTORY_PATH [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0] stringByAppendingPathComponent:@"StateMachine"]; #define MPIsNull(object) ((object) == nil || (NSNull *)(object) == [NSNull null]) +#define MPIsDictionary(object) (!MPIsNull(object) && [object isKindOfClass:[NSDictionary class]]) +#define MPIsArray(object) (!MPIsNull(object) && [object isKindOfClass:[NSArray class]]) +#define MPIsString(object) (!MPIsNull(object) && [object isKindOfClass:[NSString class]]) +#define MPIsNumber(object) (!MPIsNull(object) && [object isKindOfClass:[NSNumber class]]) + +#define MPIsNonEmptyDictionary(object) (MPIsDictionary(object) && ((NSDictionary *)object).count > 0) +#define MPIsNonEmptyArray(object) (MPIsArray(object) && ((NSArray *)object).count > 0) +#define MPIsNonEmptyString(object) (MPIsString(object) && ((NSString *)object).length > 0) +#define MPIsNonZeroNumber(object) (MPIsNumber(object) && ![(NSNumber *)object) isEqual:@0]) typedef NS_ENUM(NSInteger, MPUploadStatus) { MPUploadStatusUnknown = -1, diff --git a/mParticle-Apple-SDK/Utils/MPResponseConfig.m b/mParticle-Apple-SDK/Utils/MPResponseConfig.m index 241f5d3d..88a18cc5 100644 --- a/mParticle-Apple-SDK/Utils/MPResponseConfig.m +++ b/mParticle-Apple-SDK/Utils/MPResponseConfig.m @@ -37,14 +37,22 @@ - (nonnull instancetype)initWithConfiguration:(nonnull NSDictionary *)configurat if (!MPIsNull(self->_configuration[kMPRemoteConfigKitsKey])) { for (NSDictionary *kitDictionary in self->_configuration[kMPRemoteConfigKitsKey]) { - BOOL hasConsentKitFilter = kitDictionary[kMPConsentKitFilter] != nil; + NSDictionary *consentKitFilter = kitDictionary[kMPConsentKitFilter]; + BOOL hasConsentKitFilter = MPIsNonEmptyDictionary(consentKitFilter); + BOOL hasRegulationOrPurposeFilters = NO; NSDictionary *hashes = kitDictionary[kMPRemoteConfigKitHashesKey]; - if (hashes != nil && [hashes isKindOfClass:[NSDictionary class]]) { + if (MPIsNonEmptyDictionary(hashes)) { + + NSDictionary *regulationFilters = hashes[kMPConsentRegulationFilters]; + NSDictionary *purposeFilters = hashes[kMPConsentPurposeFilters]; + + BOOL hasRegulationFilters = MPIsNonEmptyDictionary(regulationFilters); + BOOL hasPurposeFilters = MPIsNonEmptyDictionary(purposeFilters); - if (hashes[kMPConsentRegulationFilters] != nil || hashes[kMPConsentPurposeFilters] != nil) { + if (hasRegulationFilters || hasPurposeFilters) { hasRegulationOrPurposeFilters = YES; } From fbad23dba517116752cbee5a833336136f061ed5 Mon Sep 17 00:00:00 2001 From: Peter Jenkins Date: Fri, 8 Jun 2018 16:33:12 -0400 Subject: [PATCH 07/21] Delete flaky test --- UnitTests/MPPersistenceControllerTests.mm | 35 ----------------------- 1 file changed, 35 deletions(-) diff --git a/UnitTests/MPPersistenceControllerTests.mm b/UnitTests/MPPersistenceControllerTests.mm index 10d3bed8..deb44f47 100644 --- a/UnitTests/MPPersistenceControllerTests.mm +++ b/UnitTests/MPPersistenceControllerTests.mm @@ -204,41 +204,6 @@ - (void)testResetDatabase { [self waitForExpectationsWithTimeout:DATABASE_TESTS_EXPECTATIONS_TIMEOUT handler:nil]; } -- (void)testDeleteMessages { - XCTestExpectation *expectation = [self expectationWithDescription:@"Message test"]; - - [MPPersistenceController setMpid:@2]; - - dispatch_async(messageQueue, ^{ - MPSession *session = [[MPSession alloc] initWithStartTime:[[NSDate date] timeIntervalSince1970] userId:[MPPersistenceController mpId]]; - MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; - - for (int i = 0; i < 10; ++i) { - NSString *key = [NSString stringWithFormat:@"Key%@", @(i)]; - NSString *value = [NSString stringWithFormat:@"Value%@", @(i)]; - - MPMessageBuilder *messageBuilder = [MPMessageBuilder newBuilderWithMessageType:MPMessageTypeEvent - session:session - messageInfo:@{key:value}]; - MPMessage *message = (MPMessage *)[messageBuilder build]; - [persistence saveMessage:message]; - } - - NSDictionary *messagesDictionary = [persistence fetchMessagesForUploading]; - NSMutableDictionary *sessionsDictionary = messagesDictionary[[MPPersistenceController mpId]]; - NSArray *messages = [sessionsDictionary objectForKey:[NSNumber numberWithLong:session.sessionId]]; - [persistence deleteMessages:messages]; - - messagesDictionary = [persistence fetchMessagesForUploading]; - messages = messagesDictionary[[MPPersistenceController mpId]]; - XCTAssertNil(messages, @"Should have been nil."); - - [expectation fulfill]; - }); - - [self waitForExpectationsWithTimeout:DATABASE_TESTS_EXPECTATIONS_TIMEOUT handler:nil]; -} - - (void)testUpload { MPSession *session = [[MPSession alloc] initWithStartTime:[[NSDate date] timeIntervalSince1970] userId:[MPPersistenceController mpId]]; From 9b70a0655d6a8314efcfe37c27543e27b149fbdd Mon Sep 17 00:00:00 2001 From: mParticle Automation Date: Fri, 8 Jun 2018 16:57:08 -0400 Subject: [PATCH 08/21] Update version to 7.3.11 --- Framework/Info.plist | 2 +- mParticle-Apple-SDK.podspec | 2 +- mParticle-Apple-SDK/MPIConstants.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Info.plist b/Framework/Info.plist index 1dbf5af5..4afa8633 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 7.3.10 + 7.3.11 CFBundleSignature ???? CFBundleVersion diff --git a/mParticle-Apple-SDK.podspec b/mParticle-Apple-SDK.podspec index 3d4e0518..bcaff2f4 100644 --- a/mParticle-Apple-SDK.podspec +++ b/mParticle-Apple-SDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "mParticle-Apple-SDK" - s.version = "7.3.10" + s.version = "7.3.11" s.summary = "mParticle Apple SDK." s.description = <<-DESC diff --git a/mParticle-Apple-SDK/MPIConstants.m b/mParticle-Apple-SDK/MPIConstants.m index 35a43361..d263336e 100644 --- a/mParticle-Apple-SDK/MPIConstants.m +++ b/mParticle-Apple-SDK/MPIConstants.m @@ -1,7 +1,7 @@ #import "MPIConstants.h" // mParticle SDK Version -NSString *const kMParticleSDKVersion = @"7.3.10"; +NSString *const kMParticleSDKVersion = @"7.3.11"; // Message Type (dt) NSString *const kMPMessageTypeKey = @"dt"; From c0a4687c513194add0093fcd16ef0b7d37b7e514 Mon Sep 17 00:00:00 2001 From: Sam Dozor Date: Wed, 13 Jun 2018 08:28:56 -0700 Subject: [PATCH 09/21] Add appledoc plist --- Scripts/AppledocSettings.plist | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Scripts/AppledocSettings.plist diff --git a/Scripts/AppledocSettings.plist b/Scripts/AppledocSettings.plist new file mode 100644 index 00000000..1e64a977 --- /dev/null +++ b/Scripts/AppledocSettings.plist @@ -0,0 +1,32 @@ + + + + + --project-name + mParticle Apple SDK + --logformat + 1 + --verbose + 4 + --input + + ../mParticle-Apple-SDK/mParticle.h + ../mParticle-Apple-SDK/Event + ../mParticle-Apple-SDK/Ecommerce + ../mParticle-Apple-SDK/Identity + ../mParticle-Apple-SDK/Consent + ../mParticle-Apple-SDK/MPEnums.h + ../mParticle-Apple-SDK/Segments + + --output + Docs + --no-create-docset + + --create-html + + --company-id + com.mparticle + --project-company + mParticle + + From 0894421bb2a2fb5789f61aae59ddaead19d5652e Mon Sep 17 00:00:00 2001 From: Peter Jenkins Date: Wed, 13 Jun 2018 12:29:24 -0400 Subject: [PATCH 10/21] Remove code signing settings from test targets --- mParticle-Apple-SDK.xcodeproj/project.pbxproj | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/mParticle-Apple-SDK.xcodeproj/project.pbxproj b/mParticle-Apple-SDK.xcodeproj/project.pbxproj index f9b33028..7f910675 100644 --- a/mParticle-Apple-SDK.xcodeproj/project.pbxproj +++ b/mParticle-Apple-SDK.xcodeproj/project.pbxproj @@ -1638,8 +1638,7 @@ TargetAttributes = { C911FD7B1D8A3524002A3516 = { CreatedOnToolsVersion = 8.0; - DevelopmentTeam = DLD43Y3TRP; - ProvisioningStyle = Automatic; + ProvisioningStyle = Manual; }; C935A6B21D8A2B6B00A1EE2F = { CreatedOnToolsVersion = 8.0; @@ -1653,8 +1652,7 @@ }; C9DD20841D8A18F500D3ABBE = { CreatedOnToolsVersion = 8.0; - DevelopmentTeam = DLD43Y3TRP; - ProvisioningStyle = Automatic; + ProvisioningStyle = Manual; }; }; }; @@ -2030,7 +2028,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - DEVELOPMENT_TEAM = DLD43Y3TRP; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = UnitTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( @@ -2040,6 +2039,7 @@ MACH_O_TYPE = mh_dylib; PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-tvOS-SDKTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = appletvos; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; @@ -2050,7 +2050,8 @@ isa = XCBuildConfiguration; buildSettings = { CODE_SIGN_IDENTITY = ""; - DEVELOPMENT_TEAM = DLD43Y3TRP; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = UnitTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( @@ -2060,6 +2061,7 @@ MACH_O_TYPE = mh_dylib; PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-tvOS-SDKTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SDKROOT = appletvos; TARGETED_DEVICE_FAMILY = 3; TVOS_DEPLOYMENT_TARGET = 9.0; @@ -2281,7 +2283,8 @@ C9DD208E1D8A18F600D3ABBE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - DEVELOPMENT_TEAM = DLD43Y3TRP; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/UnitTests/Libraries"; INFOPLIST_FILE = UnitTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -2294,13 +2297,15 @@ OTHER_LDFLAGS = "-ObjC"; PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-iOS-SDKTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; }; name = Debug; }; C9DD208F1D8A18F600D3ABBE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - DEVELOPMENT_TEAM = DLD43Y3TRP; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/UnitTests/Libraries"; INFOPLIST_FILE = UnitTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -2312,6 +2317,7 @@ MACH_O_TYPE = mh_dylib; PRODUCT_BUNDLE_IDENTIFIER = "com.mparticle.mParticle-iOS-SDKTests"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; }; name = Release; }; From 137a3bd86e7f84149d331fdaac496befac39771f Mon Sep 17 00:00:00 2001 From: Peter Jenkins Date: Wed, 13 Jun 2018 13:47:32 -0400 Subject: [PATCH 11/21] Update tests for iOS 12 --- UnitTests/MPBackendControllerTests.mm | 75 ++++---- UnitTests/MPPersistenceControllerTests.mm | 209 +++++++++------------- 2 files changed, 118 insertions(+), 166 deletions(-) diff --git a/UnitTests/MPBackendControllerTests.mm b/UnitTests/MPBackendControllerTests.mm index 1a4b129d..84559867 100644 --- a/UnitTests/MPBackendControllerTests.mm +++ b/UnitTests/MPBackendControllerTests.mm @@ -379,59 +379,46 @@ - (void)testBatchCycle { MPEvent *event = [[MPEvent alloc] initWithName:@"Unit Test Event" type:MPEventTypeOther]; event.info = @{@"key":@"value"}; - XCTestExpectation *expectation = [self expectationWithDescription:@"Batch cycle test"]; - dispatch_async(messageQueue, ^{ - - MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; + MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; + + [self.backendController logEvent:event + completionHandler:^(MPEvent *event, MPExecStatus execStatus) {}]; + + NSDictionary *messagesDictionary = [persistence fetchMessagesForUploading]; + NSMutableDictionary *sessionsDictionary = messagesDictionary[[MPPersistenceController mpId]]; + NSArray *messages = [sessionsDictionary objectForKey:[NSNumber numberWithLong:self->_session.sessionId]]; + XCTAssertGreaterThan(messages.count, 0, @"Messages are not being persisted."); + + for (MPMessage *message in messages) { + XCTAssertTrue(message.uploadStatus != MPUploadStatusUploaded, @"Messages are being prematurely being marked as uploaded."); + } + + MPUploadBuilder *uploadBuilder = [MPUploadBuilder newBuilderWithMpid:[MPPersistenceController mpId] sessionId:[NSNumber numberWithLong:self->_session.sessionId] messages:messages sessionTimeout:100 uploadInterval:100]; + XCTAssertNotNil(uploadBuilder, @"Upload builder should not have been nil."); + + [uploadBuilder withUserAttributes:[self.backendController userAttributesForUserId:[MPPersistenceController mpId]] deletedUserAttributes:nil]; + [uploadBuilder withUserIdentities:[self.backendController userIdentitiesForUserId:[MPPersistenceController mpId]]]; + [uploadBuilder build:^(MPUpload *upload) { + [persistence saveUpload:(MPUpload *)upload messageIds:uploadBuilder.preparedMessageIds operation:MPPersistenceOperationFlag]; - [self.backendController logEvent:event - completionHandler:^(MPEvent *event, MPExecStatus execStatus) {}]; + NSArray *messages = [persistence fetchMessagesInSession:self.session userId:[MPPersistenceController mpId]]; - NSDictionary *messagesDictionary = [persistence fetchMessagesForUploading]; - NSMutableDictionary *sessionsDictionary = messagesDictionary[[MPPersistenceController mpId]]; - NSArray *messages = [sessionsDictionary objectForKey:[NSNumber numberWithLong:self->_session.sessionId]]; - XCTAssertGreaterThan(messages.count, 0, @"Messages are not being persisted."); + XCTAssertNotNil(messages, @"There are no messages in session."); for (MPMessage *message in messages) { - XCTAssertTrue(message.uploadStatus != MPUploadStatusUploaded, @"Messages are being prematurely being marked as uploaded."); + XCTAssertTrue(message.uploadStatus == MPUploadStatusUploaded, @"Messages are not being marked as uploaded."); } - MPUploadBuilder *uploadBuilder = [MPUploadBuilder newBuilderWithMpid:[MPPersistenceController mpId] sessionId:[NSNumber numberWithLong:self->_session.sessionId] messages:messages sessionTimeout:100 uploadInterval:100]; - XCTAssertNotNil(uploadBuilder, @"Upload builder should not have been nil."); + NSArray *uploads = [persistence fetchUploads]; + XCTAssertGreaterThan(uploads.count, 0, @"Messages are not being transfered to the Uploads table."); - if (!uploadBuilder) { - return; + for (MPUpload *upload in uploads) { + [persistence deleteUpload:upload]; } - [uploadBuilder withUserAttributes:[self.backendController userAttributesForUserId:[MPPersistenceController mpId]] deletedUserAttributes:nil]; - [uploadBuilder withUserIdentities:[self.backendController userIdentitiesForUserId:[MPPersistenceController mpId]]]; - [uploadBuilder build:^(MPUpload *upload) { - [persistence saveUpload:(MPUpload *)upload messageIds:uploadBuilder.preparedMessageIds operation:MPPersistenceOperationFlag]; - - NSArray *messages = [persistence fetchMessagesInSession:self.session userId:[MPPersistenceController mpId]]; - - XCTAssertNotNil(messages, @"There are no messages in session."); - - for (MPMessage *message in messages) { - XCTAssertTrue(message.uploadStatus == MPUploadStatusUploaded, @"Messages are not being marked as uploaded."); - } - - NSArray *uploads = [persistence fetchUploads]; - XCTAssertGreaterThan(uploads.count, 0, @"Messages are not being transfered to the Uploads table."); - - for (MPUpload *upload in uploads) { - [persistence deleteUpload:upload]; - } - - uploads = [persistence fetchUploads]; - XCTAssertNil(uploads, @"Uploads are not being deleted."); - - [expectation fulfill]; - }]; - }); - - [self waitForExpectationsWithTimeout:BACKEND_TESTS_EXPECTATIONS_TIMEOUT handler:nil]; - + uploads = [persistence fetchUploads]; + XCTAssertNil(uploads, @"Uploads are not being deleted."); + }]; } - (void)testRampUpload { diff --git a/UnitTests/MPPersistenceControllerTests.mm b/UnitTests/MPPersistenceControllerTests.mm index deb44f47..08b9deb1 100644 --- a/UnitTests/MPPersistenceControllerTests.mm +++ b/UnitTests/MPPersistenceControllerTests.mm @@ -19,32 +19,22 @@ #define DATABASE_TESTS_EXPECTATIONS_TIMEOUT 1 -@interface MParticle () -+ (dispatch_queue_t)messageQueue; -@end - -@interface MPPersistenceControllerTests : XCTestCase { - dispatch_queue_t messageQueue; -} +@interface MPPersistenceControllerTests : XCTestCase @end - @implementation MPPersistenceControllerTests - (void)setUp { [super setUp]; [MParticle sharedInstance]; - messageQueue = [MParticle messageQueue]; [[MPPersistenceController sharedInstance] openDatabase]; } - (void)tearDown { - dispatch_sync(messageQueue, ^{ - MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; - [persistence deleteRecordsOlderThan:[[NSDate date] timeIntervalSince1970]]; - [persistence closeDatabase]; - }); + MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; + [persistence deleteRecordsOlderThan:[[NSDate date] timeIntervalSince1970]]; + [persistence closeDatabase]; [super tearDown]; } @@ -77,7 +67,7 @@ - (void)testMultiThreadedAccess { sessions = [persistence fetchSessions]; } }; - dispatch_async(messageQueue, ^{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ workBlock(); }); workBlock(); @@ -88,120 +78,101 @@ - (void)testPlatformSqliteAssumptions { XCTAssertEqual(safe, 2); const char *version = sqlite3_libversion(); NSString *stringVersion = [NSString stringWithCString:version encoding:NSUTF8StringEncoding]; - XCTAssertEqualObjects(stringVersion, @"3.19.3"); + XCTAssert([stringVersion isEqual:@"3.19.3"] || [stringVersion isEqual:@"3.22.0"]); } - (void)testSession { - XCTestExpectation *expectation = [self expectationWithDescription:@"Session test"]; - - dispatch_async(messageQueue, ^{ - MPSession *session = [[MPSession alloc] initWithStartTime:[[NSDate date] timeIntervalSince1970] userId:[MPPersistenceController mpId]]; - session.attributesDictionary = [@{@"key1":@"value1"} mutableCopy]; - - MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; - [persistence saveSession:session]; - - XCTAssertTrue(session.sessionId > 0, @"Session id not greater than zero: %lld", session.sessionId); - - NSMutableArray *sessions = [persistence fetchSessions]; - MPSession *fetchedSession = [sessions lastObject]; - XCTAssertEqualObjects(session, fetchedSession, @"Session and fetchedSession are not equal."); - - [persistence deleteSession:session]; - - sessions = [persistence fetchSessions]; - if (sessions) { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"sessionId == %lld", fetchedSession.sessionId]; - sessions = [NSMutableArray arrayWithArray:[sessions filteredArrayUsingPredicate:predicate]]; - XCTAssertTrue(sessions.count == 0, @"Session is not being deleted."); - } - - [expectation fulfill]; - }); - [self waitForExpectationsWithTimeout:DATABASE_TESTS_EXPECTATIONS_TIMEOUT handler:nil]; + MPSession *session = [[MPSession alloc] initWithStartTime:[[NSDate date] timeIntervalSince1970] userId:[MPPersistenceController mpId]]; + session.attributesDictionary = [@{@"key1":@"value1"} mutableCopy]; + + MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; + [persistence saveSession:session]; + + XCTAssertTrue(session.sessionId > 0, @"Session id not greater than zero: %lld", session.sessionId); + + NSMutableArray *sessions = [persistence fetchSessions]; + MPSession *fetchedSession = [sessions lastObject]; + XCTAssertEqualObjects(session, fetchedSession, @"Session and fetchedSession are not equal."); + + [persistence deleteSession:session]; + + sessions = [persistence fetchSessions]; + if (sessions) { + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"sessionId == %lld", fetchedSession.sessionId]; + sessions = [NSMutableArray arrayWithArray:[sessions filteredArrayUsingPredicate:predicate]]; + XCTAssertTrue(sessions.count == 0, @"Session is not being deleted."); + } } - (void)testMessage { - XCTestExpectation *expectation = [self expectationWithDescription:@"Message test"]; - [MPPersistenceController setMpid:@2]; - dispatch_async(messageQueue, ^{ - MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; - - MPSession *session = [[MPSession alloc] initWithStartTime:[[NSDate date] timeIntervalSince1970] userId:[MPPersistenceController mpId]]; - [persistence saveSession:session]; - - MPMessageBuilder *messageBuilder = [MPMessageBuilder newBuilderWithMessageType:MPMessageTypeEvent - session:session - messageInfo:@{@"MessageKey1":@"MessageValue1"}]; - MPMessage *message = (MPMessage *)[messageBuilder build]; - [persistence saveMessage:message]; - - XCTAssertTrue(message.messageId > 0, @"Message id not greater than zero: %lld", message.messageId); - - NSDictionary *messagesDictionary = [persistence fetchMessagesForUploading]; - NSMutableDictionary *sessionsDictionary = messagesDictionary[[MPPersistenceController mpId]]; - NSArray *messages = [sessionsDictionary objectForKey:[NSNumber numberWithLong:session.sessionId]]; - MPMessage *fetchedMessage = [messages lastObject]; - - XCTAssertEqualObjects(message, fetchedMessage, @"Message and fetchedMessage are not equal."); - - [persistence deleteSession:session]; - - messagesDictionary = [persistence fetchMessagesForUploading]; - messages = messagesDictionary[[MPPersistenceController mpId]]; - if (messages) { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"messageId == %lld", fetchedMessage.messageId]; - messages = [messages filteredArrayUsingPredicate:predicate]; - XCTAssertTrue(messages.count == 0, @"Message is not being deleted."); - } - - [expectation fulfill]; - }); - [self waitForExpectationsWithTimeout:DATABASE_TESTS_EXPECTATIONS_TIMEOUT handler:nil]; + MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; + + MPSession *session = [[MPSession alloc] initWithStartTime:[[NSDate date] timeIntervalSince1970] userId:[MPPersistenceController mpId]]; + [persistence saveSession:session]; + + MPMessageBuilder *messageBuilder = [MPMessageBuilder newBuilderWithMessageType:MPMessageTypeEvent + session:session + messageInfo:@{@"MessageKey1":@"MessageValue1"}]; + MPMessage *message = (MPMessage *)[messageBuilder build]; + [persistence saveMessage:message]; + + XCTAssertTrue(message.messageId > 0, @"Message id not greater than zero: %lld", message.messageId); + + NSDictionary *messagesDictionary = [persistence fetchMessagesForUploading]; + NSMutableDictionary *sessionsDictionary = messagesDictionary[[MPPersistenceController mpId]]; + NSArray *messages = [sessionsDictionary objectForKey:[NSNumber numberWithLong:session.sessionId]]; + MPMessage *fetchedMessage = [messages lastObject]; + + XCTAssertEqualObjects(message, fetchedMessage, @"Message and fetchedMessage are not equal."); + + [persistence deleteSession:session]; + + messagesDictionary = [persistence fetchMessagesForUploading]; + messages = messagesDictionary[[MPPersistenceController mpId]]; + if (messages) { + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"messageId == %lld", fetchedMessage.messageId]; + messages = [messages filteredArrayUsingPredicate:predicate]; + XCTAssertTrue(messages.count == 0, @"Message is not being deleted."); + } } - (void)testResetDatabase { - XCTestExpectation *expectation = [self expectationWithDescription:@"Message test"]; [MPPersistenceController setMpid:@2]; - dispatch_async(messageQueue, ^{ - MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; - - MPSession *session = [[MPSession alloc] initWithStartTime:[[NSDate date] timeIntervalSince1970] userId:[MPPersistenceController mpId]]; - [persistence saveSession:session]; - - MPMessageBuilder *messageBuilder = [MPMessageBuilder newBuilderWithMessageType:MPMessageTypeEvent - session:session - messageInfo:@{@"MessageKey1":@"MessageValue1"}]; - MPMessage *message = (MPMessage *)[messageBuilder build]; - [persistence saveMessage:message]; - - XCTAssertTrue(message.messageId > 0, @"Message id not greater than zero: %lld", message.messageId); - - NSDictionary *messagesDictionary = [persistence fetchMessagesForUploading]; - NSMutableDictionary *sessionsDictionary = messagesDictionary[[MPPersistenceController mpId]]; - NSArray *messages = [sessionsDictionary objectForKey:[NSNumber numberWithLong:session.sessionId]]; - MPMessage *fetchedMessage = [messages lastObject]; - - XCTAssertEqualObjects(message, fetchedMessage, @"Message and fetchedMessage are not equal."); - - [[MPPersistenceController sharedInstance] resetDatabase]; - - messagesDictionary = [persistence fetchMessagesForUploading]; - messages = messagesDictionary[[MPPersistenceController mpId]]; - if (messages) { - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"messageId == %lld", fetchedMessage.messageId]; - messages = [messages filteredArrayUsingPredicate:predicate]; - XCTAssertTrue(messages.count == 0, @"Message is not being deleted."); - } - - [expectation fulfill]; - }); - [self waitForExpectationsWithTimeout:DATABASE_TESTS_EXPECTATIONS_TIMEOUT handler:nil]; + MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; + + MPSession *session = [[MPSession alloc] initWithStartTime:[[NSDate date] timeIntervalSince1970] userId:[MPPersistenceController mpId]]; + [persistence saveSession:session]; + + MPMessageBuilder *messageBuilder = [MPMessageBuilder newBuilderWithMessageType:MPMessageTypeEvent + session:session + messageInfo:@{@"MessageKey1":@"MessageValue1"}]; + MPMessage *message = (MPMessage *)[messageBuilder build]; + [persistence saveMessage:message]; + + XCTAssertTrue(message.messageId > 0, @"Message id not greater than zero: %lld", message.messageId); + + NSDictionary *messagesDictionary = [persistence fetchMessagesForUploading]; + NSMutableDictionary *sessionsDictionary = messagesDictionary[[MPPersistenceController mpId]]; + NSArray *messages = [sessionsDictionary objectForKey:[NSNumber numberWithLong:session.sessionId]]; + MPMessage *fetchedMessage = [messages lastObject]; + + XCTAssertEqualObjects(message, fetchedMessage, @"Message and fetchedMessage are not equal."); + + [[MPPersistenceController sharedInstance] resetDatabase]; + + messagesDictionary = [persistence fetchMessagesForUploading]; + messages = messagesDictionary[[MPPersistenceController mpId]]; + if (messages) { + NSPredicate *predicate = [NSPredicate predicateWithFormat:@"messageId == %lld", fetchedMessage.messageId]; + messages = [messages filteredArrayUsingPredicate:predicate]; + XCTAssertTrue(messages.count == 0, @"Message is not being deleted."); + } + } - (void)testUpload { @@ -251,7 +222,7 @@ - (void)testUpload { - (void)testSegments { [MPPersistenceController setMpid:@2]; - + NSDictionary *segmentDictionary = @{@"id":@2, @"n":@"External Name 101", @"c":@[@{@"ct":@1395014265365, @@ -387,15 +358,9 @@ - (void)testConsumerInfo { [persistence saveConsumerInfo:consumerInfo]; [persistence updateConsumerInfo:consumerInfo]; - XCTestExpectation *expectation = [self expectationWithDescription:@"Consumer Info"]; - consumerInfo = [persistence fetchConsumerInfoForUserId:[MPPersistenceController mpId]]; XCTAssertNotNil(consumerInfo); [persistence deleteConsumerInfo]; - - [expectation fulfill]; - - [self waitForExpectationsWithTimeout:1 handler:nil]; } - (void)testForwardRecord { @@ -422,7 +387,7 @@ - (void)testForwardRecord { messages:@[] sessionTimeout:DEFAULT_SESSION_TIMEOUT uploadInterval:DEFAULT_DEBUG_UPLOAD_INTERVAL]; - + [uploadBuilder build: ^(MPUpload * _Nullable upload) { }]; From 10e89256897966c0272d74e1115e40a88d840caa Mon Sep 17 00:00:00 2001 From: Peter Jenkins Date: Wed, 13 Jun 2018 15:16:30 -0400 Subject: [PATCH 12/21] Remove dispatch in backend test setup/teardown --- UnitTests/MPBackendControllerTests.mm | 51 ++++++++++----------------- 1 file changed, 19 insertions(+), 32 deletions(-) diff --git a/UnitTests/MPBackendControllerTests.mm b/UnitTests/MPBackendControllerTests.mm index 84559867..30ce25e9 100644 --- a/UnitTests/MPBackendControllerTests.mm +++ b/UnitTests/MPBackendControllerTests.mm @@ -89,43 +89,30 @@ - (void)setUp { [MParticle sharedInstance]; messageQueue = [MParticle messageQueue]; - XCTestExpectation *expectation = [self expectationWithDescription:@"Set up"]; - dispatch_async(messageQueue, ^{ - [MPPersistenceController setMpid:@1]; - MPStateMachine *stateMachine = [MPStateMachine sharedInstance]; - stateMachine.apiKey = @"unit_test_app_key"; - stateMachine.secret = @"unit_test_secret"; - - [[MPPersistenceController sharedInstance] openDatabase]; - self->_session = self.backendController.session; - [self addObserver:self forKeyPath:@"backendController.session" options:NSKeyValueObservingOptionNew context:NULL]; - - [self notificationController]; - [expectation fulfill]; - }); + [MPPersistenceController setMpid:@1]; + MPStateMachine *stateMachine = [MPStateMachine sharedInstance]; + stateMachine.apiKey = @"unit_test_app_key"; + stateMachine.secret = @"unit_test_secret"; - [self waitForExpectationsWithTimeout:BACKEND_TESTS_EXPECTATIONS_TIMEOUT handler:nil]; + [[MPPersistenceController sharedInstance] openDatabase]; + self->_session = self.backendController.session; + [self addObserver:self forKeyPath:@"backendController.session" options:NSKeyValueObservingOptionNew context:NULL]; + + [self notificationController]; } - (void)tearDown { - XCTestExpectation *expectation = [self expectationWithDescription:@"Tear down"]; - dispatch_async([MParticle messageQueue], ^{ - MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; - [persistence deleteRecordsOlderThan:[[NSDate date] timeIntervalSince1970]]; - NSMutableArray *sessions = [persistence fetchSessions]; - for (MPSession *session in sessions) { - [persistence deleteSession:session]; - } - - sessions = [persistence fetchSessions]; - XCTAssertEqual(sessions.count, 0, @"Sessions have not been deleted."); - [persistence closeDatabase]; - [self removeObserver:self forKeyPath:@"backendController.session" context:NULL]; - [expectation fulfill]; - }); - - [self waitForExpectationsWithTimeout:BACKEND_TESTS_EXPECTATIONS_TIMEOUT handler:nil]; + MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; + [persistence deleteRecordsOlderThan:[[NSDate date] timeIntervalSince1970]]; + NSMutableArray *sessions = [persistence fetchSessions]; + for (MPSession *session in sessions) { + [persistence deleteSession:session]; + } + sessions = [persistence fetchSessions]; + XCTAssertEqual(sessions.count, 0, @"Sessions have not been deleted."); + [persistence closeDatabase]; + [self removeObserver:self forKeyPath:@"backendController.session" context:NULL]; [super tearDown]; } From 6bead730d596f66a6e265c20226a81b91ba460a5 Mon Sep 17 00:00:00 2001 From: BrandonStalnaker Date: Wed, 13 Jun 2018 13:11:17 -0400 Subject: [PATCH 13/21] Fix Archived Messages Crash --- UnitTests/MPBackendControllerTests.mm | 9 ++++ UnitTests/MPMessageBuilderTests.m | 55 ++++++++++++++++++++++ mParticle-Apple-SDK/Data Model/MPMessage.h | 2 +- mParticle-Apple-SDK/Data Model/MPMessage.m | 25 ++++++++++ mParticle-Apple-SDK/Ecommerce/MPCart.m | 7 ++- mParticle-Apple-SDK/MPBackendController.mm | 16 ++++--- mParticle-Apple-SDK/MPExceptionHandler.m | 44 +++++++++++------ 7 files changed, 136 insertions(+), 22 deletions(-) diff --git a/UnitTests/MPBackendControllerTests.mm b/UnitTests/MPBackendControllerTests.mm index 30ce25e9..1e31c9fa 100644 --- a/UnitTests/MPBackendControllerTests.mm +++ b/UnitTests/MPBackendControllerTests.mm @@ -16,6 +16,7 @@ #import "MPKitConfiguration.h" #import "MPKitInstanceValidator.h" #import "MPResponseConfig.h" +#import "MPExceptionHandler.h" #if TARGET_OS_IOS == 1 #import @@ -23,6 +24,14 @@ #define BACKEND_TESTS_EXPECTATIONS_TIMEOUT 10 +@interface MPExceptionHandler(Tests) + +#if TARGET_OS_IOS == 1 +- (void)handleCrashReportOccurred:(NSNotification *)notification; +#endif + +@end + #pragma mark - MParticle+Tests category @interface MParticle(Tests) diff --git a/UnitTests/MPMessageBuilderTests.m b/UnitTests/MPMessageBuilderTests.m index f5562575..28ae6ed4 100644 --- a/UnitTests/MPMessageBuilderTests.m +++ b/UnitTests/MPMessageBuilderTests.m @@ -87,6 +87,61 @@ - (void)testBuildingMessage { XCTAssertTrue([message isKindOfClass:[MPMessage class]], @"Returning the wrong kind of class instance."); } +- (void)testEncodingandDecodingMessage { + NSDictionary *messageInfo = @{@"key1":@"value1", + @"key2":@"value2", + @"key3":@"value3"}; + + MPMessageBuilder *messageBuilder = [MPMessageBuilder newBuilderWithMessageType:MPMessageTypeEvent + session:self.session + messageInfo:messageInfo]; + + XCTAssertNotNil(messageBuilder, @"Message builder should not have been nil."); + XCTAssertEqualObjects(messageBuilder.messageType, @"e", @"Message type not being set properly."); + XCTAssertEqualObjects(messageBuilder.session, self.session, @"Message session differ from the one set."); + + BOOL containsDictionary = NO; + NSArray *keys = [messageInfo allKeys]; + for (NSString *key in keys) { + containsDictionary = [messageBuilder.messageInfo[key] isEqualToString:messageInfo[key]]; + + if (!containsDictionary) { + break; + } + } + + XCTAssertTrue(containsDictionary, @"Message info dictionary is not contained in the message's dictionary."); + + NSTimeInterval timestamp = messageBuilder.timestamp; + messageBuilder = [messageBuilder withTimestamp:[[NSDate date] timeIntervalSince1970]]; + XCTAssertNotEqual(messageBuilder.timestamp, timestamp, @"Timestamp is not being updated."); + + MPMessage *message = (MPMessage *)[messageBuilder build]; + XCTAssertNotNil(message, @"MPMessage is not being built."); + XCTAssertTrue([message isKindOfClass:[MPMessage class]], @"Returning the wrong kind of class instance."); + XCTAssertNotNil(message.messageData, @"MPMessage has no data."); + + messageBuilder = [MPMessageBuilder newBuilderWithMessageType:MPMessageTypeEvent + session:nil + messageInfo:messageInfo]; + + XCTAssertNotNil(messageBuilder, @"Message builder should not have been nil."); + + message = (MPMessage *)[messageBuilder build]; + XCTAssertTrue([message isKindOfClass:[MPMessage class]], @"Returning the wrong kind of class instance."); + + NSData *messageData = [NSKeyedArchiver archivedDataWithRootObject:message]; + MPMessage *messageFromData = [NSKeyedUnarchiver unarchiveObjectWithData:messageData]; + + XCTAssertEqualObjects(message.sessionId, messageFromData.sessionId); + XCTAssertEqualObjects(message.messageType, messageFromData.messageType); + XCTAssertEqualObjects(message.messageData, messageFromData.messageData); + XCTAssertEqual(message.timestamp, messageFromData.timestamp); + XCTAssertEqual(message.messageId, messageFromData.messageId); + XCTAssertEqualObjects(message.userId, messageFromData.userId); + XCTAssertEqual(message.uploadStatus, messageFromData.uploadStatus); +} + - (void)testBuildCommerceEventProduct { MPProduct *product = [[MPProduct alloc] initWithName:@"DeLorean" sku:@"OutATime" quantity:@1 price:@4.32]; product.brand = @"DLC"; diff --git a/mParticle-Apple-SDK/Data Model/MPMessage.h b/mParticle-Apple-SDK/Data Model/MPMessage.h index 12d58482..dde7bb78 100644 --- a/mParticle-Apple-SDK/Data Model/MPMessage.h +++ b/mParticle-Apple-SDK/Data Model/MPMessage.h @@ -4,7 +4,7 @@ @class MPSession; -@interface MPMessage : MPDataModelAbstract +@interface MPMessage : MPDataModelAbstract @property (nonatomic, strong, readonly, nonnull) NSString *messageType; @property (nonatomic, strong, readonly, nonnull) NSData *messageData; diff --git a/mParticle-Apple-SDK/Data Model/MPMessage.m b/mParticle-Apple-SDK/Data Model/MPMessage.m index a6dcb249..ec3f2d8b 100644 --- a/mParticle-Apple-SDK/Data Model/MPMessage.m +++ b/mParticle-Apple-SDK/Data Model/MPMessage.m @@ -80,6 +80,31 @@ - (id)copyWithZone:(NSZone *)zone { return copyObject; } +#pragma mark NSCoding +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.sessionId forKey:@"sessionId"]; + [coder encodeInt64:self.messageId forKey:@"messageId"]; + [coder encodeObject:self.uuid forKey:@"uuid"]; + [coder encodeObject:self.messageType forKey:@"messageType"]; + [coder encodeObject:self.messageData forKey:@"messageData"]; + [coder encodeDouble:self.timestamp forKey:@"timestamp"]; + [coder encodeInteger:self.uploadStatus forKey:@"uploadStatus"]; + [coder encodeInt64:_userId.longLongValue forKey:@"mpid"]; +} + +- (id)initWithCoder:(NSCoder *)coder { + self = [self initWithSessionId:[coder decodeObjectForKey:@"sessionId"] + messageId:[coder decodeInt64ForKey:@"messageId"] + UUID:[coder decodeObjectForKey:@"uuid"] + messageType:[coder decodeObjectForKey:@"messageType"] + messageData:[coder decodeObjectForKey:@"messageData"] + timestamp:[coder decodeDoubleForKey:@"timestamp"] + uploadStatus:[coder decodeIntegerForKey:@"uploadStatus"] + userId:@([coder decodeInt64ForKey:@"mpid"])]; + + return self; +} + #pragma mark Public methods - (NSDictionary *)dictionaryRepresentation { NSError *error = nil; diff --git a/mParticle-Apple-SDK/Ecommerce/MPCart.m b/mParticle-Apple-SDK/Ecommerce/MPCart.m index 0bedfa56..2bb35798 100644 --- a/mParticle-Apple-SDK/Ecommerce/MPCart.m +++ b/mParticle-Apple-SDK/Ecommerce/MPCart.m @@ -121,7 +121,12 @@ - (MPCart *)retrieveCart { return nil; } - MPCart *cart = (MPCart *)[NSKeyedUnarchiver unarchiveObjectWithFile:_cartFile]; + MPCart *cart; + @try { + cart = (MPCart *)[NSKeyedUnarchiver unarchiveObjectWithFile:_cartFile]; + } @catch(NSException *ex) { + MPILogger(MPILogLevelError, @"Failed To retrieve cart: %@", ex); + } return cart; } diff --git a/mParticle-Apple-SDK/MPBackendController.mm b/mParticle-Apple-SDK/MPBackendController.mm index dbc17f83..9fc63b03 100644 --- a/mParticle-Apple-SDK/MPBackendController.mm +++ b/mParticle-Apple-SDK/MPBackendController.mm @@ -528,13 +528,17 @@ - (void)processPendingArchivedMessages { for (NSString *fileName in directoryContents) { NSString *filePath = [directoryPath stringByAppendingPathComponent:fileName]; - MPMessage *message = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - if (message) { - [self saveMessage:message updateSession:NO]; + @try { + MPMessage *message = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + if (message) { + [self saveMessage:message updateSession:NO]; + } + } @catch (NSException* ex) { + MPILogger(MPILogLevelError, @"Failed To retrieve crash messages from archive: %@", ex); + } @finally { + [fileManager removeItemAtPath:filePath error:nil]; } - - [fileManager removeItemAtPath:filePath error:nil]; } }]; } diff --git a/mParticle-Apple-SDK/MPExceptionHandler.m b/mParticle-Apple-SDK/MPExceptionHandler.m index 44139f0e..c6e9a7c2 100644 --- a/mParticle-Apple-SDK/MPExceptionHandler.m +++ b/mParticle-Apple-SDK/MPExceptionHandler.m @@ -221,30 +221,46 @@ typedef NS_ENUM(NSUInteger, CrashArchiveType) { id value = nil; switch (idx) { case CrashArchiveTypeCurrentState: - value = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + @try { + value = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + } @catch (NSException* ex) { + MPILogger(MPILogLevelError, @"Failed To retrieve crash current state type: %@", ex); + } break; case CrashArchiveTypeException: { - NSException *exception = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - - crashInfo[kMPErrorMessage] = [exception reason]; - crashInfo[kMPCrashingClass] = [exception name]; + @try { + NSException *exception = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + + crashInfo[kMPErrorMessage] = [exception reason]; + crashInfo[kMPCrashingClass] = [exception name]; + } @catch (NSException* ex) { + MPILogger(MPILogLevelError, @"Failed To retrieve crash exception type: %@", ex); + } } break; case CrashArchiveTypeAppImageInfo: - unarchivedDictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - key = kMPAppImageBaseAddressKey; - value = unarchivedDictionary[key]; - crashInfo[key] = value; - - key = kMPAppImageSizeKey; - value = unarchivedDictionary[key]; + @try { + unarchivedDictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + key = kMPAppImageBaseAddressKey; + value = unarchivedDictionary[key]; + crashInfo[key] = value; + + key = kMPAppImageSizeKey; + value = unarchivedDictionary[key]; + } @catch (NSException* ex) { + MPILogger(MPILogLevelError, @"Failed To retrieve crash app image info type: %@", ex); + } break; default: - unarchivedDictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; - value = unarchivedDictionary[key]; + @try { + unarchivedDictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; + value = unarchivedDictionary[key]; + } @catch (NSException* ex) { + MPILogger(MPILogLevelError, @"Failed To retrieve crash default type: %@", ex); + } break; } From a729061eb7debd073ec1d6e8fda077c7d9a852ba Mon Sep 17 00:00:00 2001 From: mParticle Automation Date: Wed, 13 Jun 2018 17:12:29 -0400 Subject: [PATCH 14/21] Update version to 7.3.12 --- Framework/Info.plist | 2 +- mParticle-Apple-SDK.podspec | 2 +- mParticle-Apple-SDK/MPIConstants.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Info.plist b/Framework/Info.plist index 4afa8633..9520d5da 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 7.3.11 + 7.3.12 CFBundleSignature ???? CFBundleVersion diff --git a/mParticle-Apple-SDK.podspec b/mParticle-Apple-SDK.podspec index bcaff2f4..d89d41f1 100644 --- a/mParticle-Apple-SDK.podspec +++ b/mParticle-Apple-SDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "mParticle-Apple-SDK" - s.version = "7.3.11" + s.version = "7.3.12" s.summary = "mParticle Apple SDK." s.description = <<-DESC diff --git a/mParticle-Apple-SDK/MPIConstants.m b/mParticle-Apple-SDK/MPIConstants.m index d263336e..30a82448 100644 --- a/mParticle-Apple-SDK/MPIConstants.m +++ b/mParticle-Apple-SDK/MPIConstants.m @@ -1,7 +1,7 @@ #import "MPIConstants.h" // mParticle SDK Version -NSString *const kMParticleSDKVersion = @"7.3.11"; +NSString *const kMParticleSDKVersion = @"7.3.12"; // Message Type (dt) NSString *const kMPMessageTypeKey = @"dt"; From 4668c18a21ba7b926a60aaf6efbdf871d417a6f4 Mon Sep 17 00:00:00 2001 From: BrandonStalnaker Date: Wed, 13 Jun 2018 17:05:03 -0400 Subject: [PATCH 15/21] Address Warnings in extension Example --- .../iOS_Extension_Example/MessagesViewController.h | 1 + .../iOS_Extension_Example/MessagesViewController.m | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Examples/CocoaPodsExample/iOS_Extension_Example/MessagesViewController.h b/Examples/CocoaPodsExample/iOS_Extension_Example/MessagesViewController.h index 18abb2de..78eed8cb 100644 --- a/Examples/CocoaPodsExample/iOS_Extension_Example/MessagesViewController.h +++ b/Examples/CocoaPodsExample/iOS_Extension_Example/MessagesViewController.h @@ -8,6 +8,7 @@ #import +API_AVAILABLE(ios(10.0)) @interface MessagesViewController : MSMessagesAppViewController @end diff --git a/Examples/CocoaPodsExample/iOS_Extension_Example/MessagesViewController.m b/Examples/CocoaPodsExample/iOS_Extension_Example/MessagesViewController.m index 2c12f2fb..6a5d986d 100644 --- a/Examples/CocoaPodsExample/iOS_Extension_Example/MessagesViewController.m +++ b/Examples/CocoaPodsExample/iOS_Extension_Example/MessagesViewController.m @@ -44,14 +44,14 @@ - (void)didReceiveMemoryWarning { #pragma mark - Conversation Handling --(void)didBecomeActiveWithConversation:(MSConversation *)conversation { +-(void)didBecomeActiveWithConversation:(MSConversation *)conversation NS_AVAILABLE_IOS(10_0){ // Called when the extension is about to move from the inactive to active state. // This will happen when the extension is about to present UI. // Use this method to configure the extension and restore previously stored state. } --(void)willResignActiveWithConversation:(MSConversation *)conversation { +-(void)willResignActiveWithConversation:(MSConversation *)conversation NS_AVAILABLE_IOS(10_0){ // Called when the extension is about to move from the active to inactive state. // This will happen when the user dissmises the extension, changes to a different // conversation or quits Messages. From 69bce880135feedb3aef310ad4c6057bb2da8839 Mon Sep 17 00:00:00 2001 From: Peter Jenkins <5166653+peterjenkins@users.noreply.github.com> Date: Thu, 14 Jun 2018 16:32:42 -0400 Subject: [PATCH 16/21] Set user identities sync in identity handler --- mParticle-Apple-SDK/Identity/MPIdentityApi.m | 6 +-- mParticle-Apple-SDK/Identity/MParticleUser.m | 42 ++++++++++++-------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/mParticle-Apple-SDK/Identity/MPIdentityApi.m b/mParticle-Apple-SDK/Identity/MPIdentityApi.m index d7252a79..a8a5ba5b 100644 --- a/mParticle-Apple-SDK/Identity/MPIdentityApi.m +++ b/mParticle-Apple-SDK/Identity/MPIdentityApi.m @@ -45,7 +45,7 @@ @interface MPBackendController () @interface MParticleUser () -- (void)setUserIdentity:(NSString *)identityString identityType:(MPUserIdentity)identityType; +- (void)setUserIdentitySync:(NSString *)identityString identityType:(MPUserIdentity)identityType; - (void)setUserId:(NSNumber *)userId; @end @@ -81,7 +81,7 @@ - (void)onModifyRequestComplete:(MPIdentityApiRequest *)request httpResponse:(MP if ((NSNull *)identityValue == [NSNull null]) { identityValue = nil; } - [self.currentUser setUserIdentity:identityValue identityType:identityType]; + [self.currentUser setUserIdentitySync:identityValue identityType:identityType]; }]; } @@ -138,7 +138,7 @@ - (void)onIdentityRequestComplete:(MPIdentityApiRequest *)request identityReques if (request.userIdentities) { [request.userIdentities enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, id _Nonnull identityValue, BOOL * _Nonnull stop) { MPUserIdentity identityType = (MPUserIdentity)key.intValue; - [self.currentUser setUserIdentity:identityValue identityType:identityType]; + [self.currentUser setUserIdentitySync:identityValue identityType:identityType]; }]; } diff --git a/mParticle-Apple-SDK/Identity/MParticleUser.m b/mParticle-Apple-SDK/Identity/MParticleUser.m index 8e1bc31e..3d6049f0 100644 --- a/mParticle-Apple-SDK/Identity/MParticleUser.m +++ b/mParticle-Apple-SDK/Identity/MParticleUser.m @@ -109,26 +109,34 @@ - (void)setUserIdentity:(NSString *)identityString identityType:(MPUserIdentity) NSDate *timestamp = [NSDate date]; dispatch_async([MParticle messageQueue], ^{ - [self.backendController setUserIdentity:identityString - identityType:identityType - timestamp:timestamp - completionHandler:^(NSString *identityString, MPUserIdentity identityType, MPExecStatus execStatus) { - - if (execStatus == MPExecStatusSuccess) { - MPILogDebug(@"Set user identity: %@", identityString); - - // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setUserIdentity:identityType:) - userIdentity:identityString - identityType:identityType - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - [kit setUserIdentity:identityString identityType:identityType]; - }]; - } - }]; + [self setUserIdentitySync:identityString identityType:identityType timestamp:timestamp]; }); } +- (void)setUserIdentitySync:(NSString *)identityString identityType:(MPUserIdentity)identityType { + [self setUserIdentitySync:identityString identityType:identityType timestamp:[NSDate date]]; +} + +- (void)setUserIdentitySync:(NSString *)identityString identityType:(MPUserIdentity)identityType timestamp:(NSDate *)timestamp { + [self.backendController setUserIdentity:identityString + identityType:identityType + timestamp:timestamp + completionHandler:^(NSString *identityString, MPUserIdentity identityType, MPExecStatus execStatus) { + + if (execStatus == MPExecStatusSuccess) { + MPILogDebug(@"Set user identity: %@", identityString); + + // Forwarding calls to kits + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setUserIdentity:identityType:) + userIdentity:identityString + identityType:identityType + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + [kit setUserIdentity:identityString identityType:identityType]; + }]; + } + }]; +} + - (nullable NSNumber *)incrementUserAttribute:(NSString *)key byValue:(NSNumber *)value { dispatch_async([MParticle messageQueue], ^{ From 7d5386416524f2a28d2ff4e223d2c7a6e9b8c839 Mon Sep 17 00:00:00 2001 From: mParticle Automation Date: Thu, 14 Jun 2018 17:06:37 -0400 Subject: [PATCH 17/21] Update version to 7.3.13 --- Framework/Info.plist | 2 +- mParticle-Apple-SDK.podspec | 2 +- mParticle-Apple-SDK/MPIConstants.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Info.plist b/Framework/Info.plist index 9520d5da..fde8e5ff 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 7.3.12 + 7.3.13 CFBundleSignature ???? CFBundleVersion diff --git a/mParticle-Apple-SDK.podspec b/mParticle-Apple-SDK.podspec index d89d41f1..6d8603cd 100644 --- a/mParticle-Apple-SDK.podspec +++ b/mParticle-Apple-SDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "mParticle-Apple-SDK" - s.version = "7.3.12" + s.version = "7.3.13" s.summary = "mParticle Apple SDK." s.description = <<-DESC diff --git a/mParticle-Apple-SDK/MPIConstants.m b/mParticle-Apple-SDK/MPIConstants.m index 30a82448..4edfcb27 100644 --- a/mParticle-Apple-SDK/MPIConstants.m +++ b/mParticle-Apple-SDK/MPIConstants.m @@ -1,7 +1,7 @@ #import "MPIConstants.h" // mParticle SDK Version -NSString *const kMParticleSDKVersion = @"7.3.12"; +NSString *const kMParticleSDKVersion = @"7.3.13"; // Message Type (dt) NSString *const kMPMessageTypeKey = @"dt"; From 88706aaf012c6ef165848561d797d3f44b46ed42 Mon Sep 17 00:00:00 2001 From: Peter Jenkins <5166653+peterjenkins@users.noreply.github.com> Date: Tue, 26 Jun 2018 10:31:21 -0400 Subject: [PATCH 18/21] Dispatch to all kit APIs on the main thread This introduces several changes to the threading structure of the SDK: - the SDK will call all 3rd-party kit APIs on the main thread - the SDK maintains the existing "message" queue for recording messages, and introduces a "network" queue to perform network requests This addresses several deadlocking and timing issues present in recent versions of the SDK. --- UnitTests/MPBackendControllerTests.mm | 179 +++++----- UnitTests/MPKitContainerTests.m | 183 +++------- UnitTests/MPURLRequestBuilderTests.m | 9 + .../MPAppNotificationHandler.mm | 99 +++--- mParticle-Apple-SDK/Identity/MPIdentityApi.m | 106 +++--- mParticle-Apple-SDK/Identity/MParticleUser.m | 226 ++++++------ mParticle-Apple-SDK/Kits/MPKitContainer.h | 2 +- mParticle-Apple-SDK/Kits/MPKitContainer.mm | 334 ++++++++---------- mParticle-Apple-SDK/MPBackendController.mm | 146 ++++---- mParticle-Apple-SDK/Utils/MPResponseConfig.m | 2 +- .../Utils/MPSearchAdsAttribution.m | 54 +-- mParticle-Apple-SDK/mParticle.m | 234 ++++++------ 12 files changed, 760 insertions(+), 814 deletions(-) diff --git a/UnitTests/MPBackendControllerTests.mm b/UnitTests/MPBackendControllerTests.mm index 1e31c9fa..c206b3b9 100644 --- a/UnitTests/MPBackendControllerTests.mm +++ b/UnitTests/MPBackendControllerTests.mm @@ -785,104 +785,96 @@ - (void)testUserAttributes { } - (void)testUserAttributeChanged { - XCTestExpectation *expectation = [self expectationWithDescription:@"User attribute changed"]; - dispatch_async(messageQueue, ^{ - MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; - [persistence saveSession:self.backendController.session]; - - [self.backendController setUserAttribute:@"TardisModel" value:@"Police Call Box" timestamp:[NSDate date] completionHandler:nil]; - - NSDictionary *userAttributes = [self.backendController userAttributesForUserId:[MPPersistenceController mpId]]; - XCTAssertEqualObjects(userAttributes[@"TardisModel"], @"Police Call Box"); - - NSArray *messages = [persistence fetchMessagesInSession:self.backendController.session userId:[MPPersistenceController mpId]]; - XCTAssertNotNil(messages); - XCTAssertEqual(messages.count, 1); - - MPMessage *message = [messages firstObject]; - XCTAssertNotNil(message); - - NSDictionary *messageDictionary = [message dictionaryRepresentation]; - XCTAssertEqualObjects(@"uac", messageDictionary[@"dt"]); - XCTAssertEqualObjects(@"Police Call Box", messageDictionary[@"nv"]); - XCTAssertEqualObjects(@"TardisModel", messageDictionary[@"n"]); - XCTAssertEqualObjects(@NO, messageDictionary[@"d"]); - - [persistence deleteSession:self.backendController.session]; - messages = [persistence fetchMessagesInSession:self.backendController.session userId:[MPPersistenceController mpId]]; - XCTAssertNil(messages); - - [self.backendController removeUserAttribute:@"TardisModel" timestamp:[NSDate date] completionHandler:nil]; - messages = [persistence fetchMessagesInSession:self.backendController.session userId:[MPPersistenceController mpId]]; - message = [messages firstObject]; - messageDictionary = [message dictionaryRepresentation]; - XCTAssertEqualObjects(@"uac", messageDictionary[@"dt"]); - XCTAssertEqualObjects([NSNull null], messageDictionary[@"nv"]); - XCTAssertEqualObjects(@"Police Call Box", messageDictionary[@"ov"]); - XCTAssertEqualObjects(@"TardisModel", messageDictionary[@"n"]); - XCTAssertEqualObjects(@YES, messageDictionary[@"d"]); - [expectation fulfill]; - }); - [self waitForExpectationsWithTimeout:BACKEND_TESTS_EXPECTATIONS_TIMEOUT handler:nil]; + MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; + [persistence saveSession:self.backendController.session]; + + [self.backendController setUserAttribute:@"TardisModel" value:@"Police Call Box" timestamp:[NSDate date] completionHandler:nil]; + + NSDictionary *userAttributes = [self.backendController userAttributesForUserId:[MPPersistenceController mpId]]; + XCTAssertEqualObjects(userAttributes[@"TardisModel"], @"Police Call Box"); + + NSArray *messages = [persistence fetchMessagesInSession:self.backendController.session userId:[MPPersistenceController mpId]]; + XCTAssertNotNil(messages); + XCTAssertEqual(messages.count, 1); + + MPMessage *message = [messages firstObject]; + XCTAssertNotNil(message); + + NSDictionary *messageDictionary = [message dictionaryRepresentation]; + XCTAssertEqualObjects(@"uac", messageDictionary[@"dt"]); + XCTAssertEqualObjects(@"Police Call Box", messageDictionary[@"nv"]); + XCTAssertEqualObjects(@"TardisModel", messageDictionary[@"n"]); + XCTAssertEqualObjects(@NO, messageDictionary[@"d"]); + + [persistence deleteSession:self.backendController.session]; + messages = [persistence fetchMessagesInSession:self.backendController.session userId:[MPPersistenceController mpId]]; + XCTAssertNil(messages); + + [self.backendController removeUserAttribute:@"TardisModel" timestamp:[NSDate date] completionHandler:nil]; + messages = [persistence fetchMessagesInSession:self.backendController.session userId:[MPPersistenceController mpId]]; + message = [messages firstObject]; + messageDictionary = [message dictionaryRepresentation]; + XCTAssertEqualObjects(@"uac", messageDictionary[@"dt"]); + XCTAssertEqualObjects([NSNull null], messageDictionary[@"nv"]); + XCTAssertEqualObjects(@"Police Call Box", messageDictionary[@"ov"]); + XCTAssertEqualObjects(@"TardisModel", messageDictionary[@"n"]); + XCTAssertEqualObjects(@YES, messageDictionary[@"d"]); } - (void)testUserIdentityChanged { XCTestExpectation *expectation = [self expectationWithDescription:@"User identity changed"]; __weak MPBackendControllerTests *weakSelf = self; - dispatch_async(messageQueue, ^{ - MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; - [persistence saveSession:weakSelf.session]; - - [weakSelf.backendController setUserIdentity:@"The Most Interesting Man in the World" identityType:MPUserIdentityCustomerId timestamp:[NSDate date] completionHandler:^(NSString * _Nullable identityString, MPUserIdentity identityType, MPExecStatus execStatus) { - }]; - - __block NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF[%@] == %@", @"n", @(MPUserIdentityCustomerId)]; - __block NSDictionary *userIdentity = [[[self.backendController userIdentitiesForUserId:[MPPersistenceController mpId]] filteredArrayUsingPredicate:predicate] lastObject]; - XCTAssertNotNil(userIdentity); - XCTAssertEqualObjects(userIdentity[@"i"], @"The Most Interesting Man in the World"); - XCTAssertEqualObjects(userIdentity[@"n"], @(MPUserIdentityCustomerId)); + MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; + [persistence saveSession:weakSelf.session]; + + [weakSelf.backendController setUserIdentity:@"The Most Interesting Man in the World" identityType:MPUserIdentityCustomerId timestamp:[NSDate date] completionHandler:^(NSString * _Nullable identityString, MPUserIdentity identityType, MPExecStatus execStatus) { + }]; + + __block NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF[%@] == %@", @"n", @(MPUserIdentityCustomerId)]; + __block NSDictionary *userIdentity = [[[self.backendController userIdentitiesForUserId:[MPPersistenceController mpId]] filteredArrayUsingPredicate:predicate] lastObject]; + XCTAssertNotNil(userIdentity); + XCTAssertEqualObjects(userIdentity[@"i"], @"The Most Interesting Man in the World"); + XCTAssertEqualObjects(userIdentity[@"n"], @(MPUserIdentityCustomerId)); + + __block NSArray *messages = [persistence fetchMessagesInSession:self.session userId:self.session.userId]; + XCTAssertNotNil(messages); + XCTAssertEqual(messages.count, 1); + + __block MPMessage *message = [messages firstObject]; + XCTAssertNotNil(message); + + __block NSDictionary *messageDictionary = [message dictionaryRepresentation]; + XCTAssertEqualObjects(@"uic", messageDictionary[@"dt"]); + XCTAssertNotNil(messageDictionary[@"ni"]); + userIdentity = messageDictionary[@"ni"]; + XCTAssertEqualObjects(userIdentity[@"i"], @"The Most Interesting Man in the World"); + XCTAssertEqualObjects(userIdentity[@"n"], @(MPUserIdentityCustomerId)); + + [persistence deleteSession:self.session]; + messages = [persistence fetchMessagesInSession:self.session userId:[MPPersistenceController mpId]]; + XCTAssertNil(messages); + + weakSelf.backendController.session = nil; + [weakSelf.backendController setUserIdentity:nil identityType:MPUserIdentityCustomerId timestamp:[NSDate date] completionHandler:^(NSString * _Nullable identityString, MPUserIdentity identityType, MPExecStatus execStatus) { + userIdentity = [[[weakSelf.backendController userIdentitiesForUserId:[MPPersistenceController mpId]] filteredArrayUsingPredicate:predicate] lastObject]; + XCTAssertNil(userIdentity); - __block NSArray *messages = [persistence fetchMessagesInSession:self.session userId:self.session.userId]; + messages = [persistence fetchMessagesInSession:weakSelf.session userId:[MPPersistenceController mpId]]; XCTAssertNotNil(messages); - XCTAssertEqual(messages.count, 1); + XCTAssertEqual(messages.count, 2); - __block MPMessage *message = [messages firstObject]; + predicate = [NSPredicate predicateWithFormat:@"messageType == %@", @"uic"]; + message = [[messages filteredArrayUsingPredicate:predicate] firstObject]; XCTAssertNotNil(message); - __block NSDictionary *messageDictionary = [message dictionaryRepresentation]; + messageDictionary = [message dictionaryRepresentation]; XCTAssertEqualObjects(@"uic", messageDictionary[@"dt"]); - XCTAssertNotNil(messageDictionary[@"ni"]); - userIdentity = messageDictionary[@"ni"]; + XCTAssertNil(messageDictionary[@"ni"]); + userIdentity = messageDictionary[@"oi"]; XCTAssertEqualObjects(userIdentity[@"i"], @"The Most Interesting Man in the World"); XCTAssertEqualObjects(userIdentity[@"n"], @(MPUserIdentityCustomerId)); - - [persistence deleteSession:self.session]; - messages = [persistence fetchMessagesInSession:self.session userId:[MPPersistenceController mpId]]; - XCTAssertNil(messages); - - weakSelf.backendController.session = nil; - [weakSelf.backendController setUserIdentity:nil identityType:MPUserIdentityCustomerId timestamp:[NSDate date] completionHandler:^(NSString * _Nullable identityString, MPUserIdentity identityType, MPExecStatus execStatus) { - userIdentity = [[[weakSelf.backendController userIdentitiesForUserId:[MPPersistenceController mpId]] filteredArrayUsingPredicate:predicate] lastObject]; - XCTAssertNil(userIdentity); - - messages = [persistence fetchMessagesInSession:weakSelf.session userId:[MPPersistenceController mpId]]; - XCTAssertNotNil(messages); - XCTAssertEqual(messages.count, 2); - - predicate = [NSPredicate predicateWithFormat:@"messageType == %@", @"uic"]; - message = [[messages filteredArrayUsingPredicate:predicate] firstObject]; - XCTAssertNotNil(message); - - messageDictionary = [message dictionaryRepresentation]; - XCTAssertEqualObjects(@"uic", messageDictionary[@"dt"]); - XCTAssertNil(messageDictionary[@"ni"]); - userIdentity = messageDictionary[@"oi"]; - XCTAssertEqualObjects(userIdentity[@"i"], @"The Most Interesting Man in the World"); - XCTAssertEqualObjects(userIdentity[@"n"], @(MPUserIdentityCustomerId)); - [expectation fulfill]; - }]; - - }); + [expectation fulfill]; + }]; [self waitForExpectationsWithTimeout:BACKEND_TESTS_EXPECTATIONS_TIMEOUT handler:nil]; } @@ -946,14 +938,15 @@ - (void)testSetLocation { } - (void)testSessionAttributesAndIncrement { - [self.backendController setSessionAttribute:_session key:@"foo-session-attribute-1" value:@"foo-session-value-1"]; - XCTAssertEqualObjects(_session.attributesDictionary[@"foo-session-attribute-1"], @"foo-session-value-1"); - [self.backendController setSessionAttribute:_session key:@"foo-session-attribute-1" value:@"foo-session-value-2"]; - XCTAssertEqualObjects(_session.attributesDictionary[@"foo-session-attribute-1"], @"foo-session-value-2"); - [self.backendController setSessionAttribute:_session key:@"foo-session-attribute-1" value:@2]; - XCTAssertEqualObjects(_session.attributesDictionary[@"foo-session-attribute-1"], @2); - [self.backendController incrementSessionAttribute:_session key:@"foo-session-attribute-1" byValue:@3]; - XCTAssertEqualObjects(_session.attributesDictionary[@"foo-session-attribute-1"], @5); + MPSession *session = [[MPSession alloc] init]; + [self.backendController setSessionAttribute:session key:@"foo-session-attribute-1" value:@"foo-session-value-1"]; + XCTAssertEqualObjects(session.attributesDictionary[@"foo-session-attribute-1"], @"foo-session-value-1"); + [self.backendController setSessionAttribute:session key:@"foo-session-attribute-1" value:@"foo-session-value-2"]; + XCTAssertEqualObjects(session.attributesDictionary[@"foo-session-attribute-1"], @"foo-session-value-2"); + [self.backendController setSessionAttribute:session key:@"foo-session-attribute-1" value:@2]; + XCTAssertEqualObjects(session.attributesDictionary[@"foo-session-attribute-1"], @2); + [self.backendController incrementSessionAttribute:session key:@"foo-session-attribute-1" byValue:@3]; + XCTAssertEqualObjects(session.attributesDictionary[@"foo-session-attribute-1"], @5); } @end diff --git a/UnitTests/MPKitContainerTests.m b/UnitTests/MPKitContainerTests.m index f8fec587..d02a94c0 100644 --- a/UnitTests/MPKitContainerTests.m +++ b/UnitTests/MPKitContainerTests.m @@ -221,6 +221,7 @@ - (void)testRemoveKitConfiguration { NSArray __block *kitConfigs = @[configuration1, configuration2]; XCTestExpectation *expectation = [self expectationWithDescription:@"Test instance"]; + [MParticle sharedInstance]; dispatch_async([MParticle messageQueue], ^{ NSString *eTag = @"1.618-2.718-3.141-42"; NSDictionary *configuration = @{kMPRemoteConfigKitsKey:kitConfigs, @@ -234,6 +235,7 @@ - (void)testRemoveKitConfiguration { [MPResponseConfig save:responseConfig eTag:eTag]; + dispatch_sync(dispatch_get_main_queue(), ^{ }); XCTAssertEqual(@"cool app key", [self->kitContainer.kitConfigurations objectForKey:@(42)].configuration[@"appId"]); NSArray *directoryContents = [[MPIUserDefaults standardUserDefaults] getKitConfigurations]; @@ -501,44 +503,6 @@ - (void)testForwardQueueItem { XCTAssertEqual(kitContainer.forwardQueue.count, 0, @"Should have been equal."); } -- (void)testAssortedItems { - NSDictionary *configuration = @{ - @"id":@42, - @"as":@{ - @"appId":@"MyAppId" - } - }; - - MPKitConfiguration *kitConfiguration = [[MPKitConfiguration alloc] initWithDictionary:configuration]; - [kitContainer startKit:@42 configuration:kitConfiguration]; - - NSNotification *notification = [[NSNotification alloc] initWithName:@"Test Launching" - object:self - userInfo:@{@"deep":@"linking"}]; - - [kitContainer handleApplicationDidFinishLaunching:notification]; - - NSSet> *registeredKits = [MPKitContainer registeredKits]; - id kit; - for (kit in registeredKits) { - id wrapperInstance = [kit wrapperInstance]; - NSNumber *kitCode = ((MPKitRegister *)kit).code; - - if ([kitCode isEqualToNumber:@42]) { - NSDictionary *launchOptions = [(id)wrapperInstance launchOptions]; - XCTAssertNotNil(launchOptions, @"Should not have been nil."); - } - - NSString *name = [kitContainer nameForKitCode:kitCode]; - XCTAssertEqualObjects(name, [kit name], @"Should have been equal."); - } - - [kitContainer handleApplicationDidBecomeActive:nil]; - - NSDictionary *mapping = [kitContainer methodMessageTypeMapping]; - XCTAssertNotNil(mapping, @"Should not have been nil."); -} - - (void)testFilterEventType { NSArray *configurations = @[ @{ @@ -805,8 +769,6 @@ - (void)testFilterForSelector { } - (void)testFilterForUserAttribute { - XCTestExpectation *expectation = [self expectationWithDescription:@"Filtering user attributes"]; - NSArray *configurations = @[ @{ @"id":@(42), @@ -850,7 +812,6 @@ - (void)testFilterForUserAttribute { key = @"Dinosaur"; values = [@[@"T-Rex", @"Short arms", @"Omnivore"] mutableCopy]; - dispatch_async([MParticle messageQueue], ^{ [self->kitContainer forwardSDKCall:@selector(setUserAttribute:values:) userAttributeKey:key value:values @@ -859,12 +820,9 @@ - (void)testFilterForUserAttribute { MPKitExecStatus *execStatus = [kit setUserAttribute:key values:values]; XCTAssertEqual(execStatus.returnCode, MPKitReturnCodeSuccess); - - [expectation fulfill]; + }]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; + } - (void)testNotForwardUserAttributeList { @@ -1256,8 +1214,6 @@ - (void)testFilterCommerceEvent_TransactionAttributes { } - (void)testForwardAppsFlyerEvent { - XCTestExpectation *expectation = [self expectationWithDescription:@"AppsFlyer projection"]; - [self setUserAttributesAndIdentities]; NSString *configurationStr = @"{ \ @@ -1360,29 +1316,21 @@ - (void)testForwardAppsFlyerEvent { MPEvent *event = [[MPEvent alloc] initWithName:@"subscription_success" type:MPEventTypeTransaction]; event.info = @{@"plan":@"premium", @"plan_color":@"gold", @"boolean":@YES}; - dispatch_async([MParticle messageQueue], ^{ - [self->kitContainer forwardSDKCall:@selector(logEvent:) - event:event - messageType:MPMessageTypeEvent - userInfo:nil - kitHandler:^(id _Nonnull kit, MPEvent * _Nullable forwardEvent, MPKitExecStatus *__autoreleasing _Nonnull * _Nonnull execStatus) { - if ([[[kit class] kitCode] isEqualToNumber:@(MPKitInstanceAppsFlyer)]) { - XCTAssertNotNil(forwardEvent); - XCTAssertEqualObjects(forwardEvent.name, @"new_premium_subscriber"); - XCTAssertNotNil(forwardEvent.info); - XCTAssertEqual(forwardEvent.info.count, 3); - - [expectation fulfill]; - } - }]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; + [self->kitContainer forwardSDKCall:@selector(logEvent:) + event:event + messageType:MPMessageTypeEvent + userInfo:nil + kitHandler:^(id _Nonnull kit, MPEvent * _Nullable forwardEvent, MPKitExecStatus *__autoreleasing _Nonnull * _Nonnull execStatus) { + if ([[[kit class] kitCode] isEqualToNumber:@(MPKitInstanceAppsFlyer)]) { + XCTAssertNotNil(forwardEvent); + XCTAssertEqualObjects(forwardEvent.name, @"new_premium_subscriber"); + XCTAssertNotNil(forwardEvent.info); + XCTAssertEqual(forwardEvent.info.count, 3); + } + }]; } - (void)testForwardAppsFlyerCommerceEvent { - XCTestExpectation *expectation = [self expectationWithDescription:@"AppsFlyer ecommerce projection"]; - [self setUserAttributesAndIdentities]; NSString *configurationStr = @"{ \ @@ -1539,27 +1487,19 @@ - (void)testForwardAppsFlyerCommerceEvent { transactionAttributes.transactionId = @"42"; commerceEvent.transactionAttributes = transactionAttributes; - dispatch_async([MParticle messageQueue], ^{ - [self->kitContainer forwardCommerceEventCall:commerceEvent - kitHandler:^(id _Nonnull kit, MPKitFilter * _Nonnull kitFilter, MPKitExecStatus *__autoreleasing _Nonnull * _Nonnull execStatus) { - if ([[[kit class] kitCode] isEqualToNumber:@(MPKitInstanceAppsFlyer)]) { - MPEvent *event = kitFilter.forwardEvent; - XCTAssertEqualObjects(event.info[@"af_quantity"], @"1"); - XCTAssertEqualObjects(event.info[@"af_content_id"], @"OutATime"); - XCTAssertEqualObjects(event.info[@"af_content_type"], @"Time Machine"); - XCTAssertEqualObjects(event.name, @"af_add_to_cart"); - - [expectation fulfill]; - } - }]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; + [self->kitContainer forwardCommerceEventCall:commerceEvent + kitHandler:^(id _Nonnull kit, MPKitFilter * _Nonnull kitFilter, MPKitExecStatus *__autoreleasing _Nonnull * _Nonnull execStatus) { + if ([[[kit class] kitCode] isEqualToNumber:@(MPKitInstanceAppsFlyer)]) { + MPEvent *event = kitFilter.forwardEvent; + XCTAssertEqualObjects(event.info[@"af_quantity"], @"1"); + XCTAssertEqualObjects(event.info[@"af_content_id"], @"OutATime"); + XCTAssertEqualObjects(event.info[@"af_content_type"], @"Time Machine"); + XCTAssertEqualObjects(event.name, @"af_add_to_cart"); + } + }]; } - (void)testMatchArrayProjection { - XCTestExpectation *expectation = [self expectationWithDescription:@"Match array projection"]; - [self setUserAttributesAndIdentities]; NSString *configurationStr = @"{ \ @@ -1639,8 +1579,7 @@ - (void)testMatchArrayProjection { MPEvent *event = [[MPEvent alloc] initWithName:@"SUBSCRIPTION_END" type:MPEventTypeTransaction]; event.info = @{@"plan_id":@"3", @"outcome":@"new_subscription"}; __block NSMutableArray *foundEventNames = [NSMutableArray arrayWithCapacity:2]; - - dispatch_async([MParticle messageQueue], ^{ + [self->kitContainer forwardSDKCall:@selector(logEvent:) event:event messageType:MPMessageTypeEvent @@ -1656,18 +1595,11 @@ - (void)testMatchArrayProjection { if (foundEventNames.count == 2) { XCTAssertTrue([foundEventNames containsObject:@"X_NEW_SUBSCRIPTION"]); XCTAssertTrue([foundEventNames containsObject:@"X_NEW_NOAH_SUBSCRIPTION"]); - [expectation fulfill]; } - } - }]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; + }}]; } - (void)testNonMatchingMatchArrayProjection { - XCTestExpectation *expectation = [self expectationWithDescription:@"Non-matching match array projection"]; - [self setUserAttributesAndIdentities]; NSString *configurationStr = @"{ \ @@ -1723,27 +1655,20 @@ - (void)testNonMatchingMatchArrayProjection { MPEvent *event = [[MPEvent alloc] initWithName:@"SUBSCRIPTION_END" type:MPEventTypeTransaction]; event.info = @{@"plan_id":@"3", @"outcome":@"new_subscription", @"gender":@"female"}; - dispatch_async([MParticle messageQueue], ^{ - [self->kitContainer forwardSDKCall:@selector(logEvent:) - event:event - messageType:MPMessageTypeEvent - userInfo:nil - kitHandler:^(id _Nonnull kit, MPEvent * _Nullable forwardEvent, MPKitExecStatus *__autoreleasing _Nonnull * _Nonnull execStatus) { - if ([[[kit class] kitCode] isEqualToNumber:@(MPKitInstanceAppsFlyer)]) { - XCTAssertNotNil(forwardEvent); - XCTAssertNotEqualObjects(forwardEvent.name, @"X_NEW_MALE_SUBSCRIPTION"); - XCTAssertEqualObjects(forwardEvent.name, @"SUBSCRIPTION_END"); - [expectation fulfill]; - } - }]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; + [self->kitContainer forwardSDKCall:@selector(logEvent:) + event:event + messageType:MPMessageTypeEvent + userInfo:nil + kitHandler:^(id _Nonnull kit, MPEvent * _Nullable forwardEvent, MPKitExecStatus *__autoreleasing _Nonnull * _Nonnull execStatus) { + if ([[[kit class] kitCode] isEqualToNumber:@(MPKitInstanceAppsFlyer)]) { + XCTAssertNotNil(forwardEvent); + XCTAssertNotEqualObjects(forwardEvent.name, @"X_NEW_MALE_SUBSCRIPTION"); + XCTAssertEqualObjects(forwardEvent.name, @"SUBSCRIPTION_END"); + } + }]; } - (void)testNonMatchingAttributeArrayProjection { - XCTestExpectation *expectation = [self expectationWithDescription:@"Non-matching attribute array projection"]; - [self setUserAttributesAndIdentities]; NSString *configurationStr = @"{ \ @@ -1790,7 +1715,6 @@ - (void)testNonMatchingAttributeArrayProjection { MPEvent *event = [[MPEvent alloc] initWithName:@"SUBSCRIPTION_END" type:MPEventTypeTransaction]; event.info = @{@"outcome":@"not_new_subscription"}; - dispatch_async([MParticle messageQueue], ^{ [self->kitContainer forwardSDKCall:@selector(logEvent:) event:event messageType:MPMessageTypeEvent @@ -1800,17 +1724,11 @@ - (void)testNonMatchingAttributeArrayProjection { XCTAssertNotNil(forwardEvent); XCTAssertNotEqualObjects(forwardEvent.name, @"X_NEW_SUBSCRIPTION"); XCTAssertEqualObjects(forwardEvent.name, @"SUBSCRIPTION_END"); - [expectation fulfill]; } }]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; } - (void)testHashProjection { - XCTestExpectation *expectation = [self expectationWithDescription:@"Hash projection"]; - [self setUserAttributesAndIdentities]; NSString *configurationStr = @"{ \ @@ -1861,7 +1779,6 @@ - (void)testHashProjection { MPEvent *event = [[MPEvent alloc] initWithName:@"test_string" type:MPEventTypeOther]; event.info = @{@"plan":@"premium"}; - dispatch_async([MParticle messageQueue], ^{ [self->kitContainer forwardSDKCall:@selector(logEvent:) event:event messageType:MPMessageTypeEvent @@ -1873,18 +1790,11 @@ - (void)testHashProjection { XCTAssertNotNil(forwardEvent.info); XCTAssertEqual(forwardEvent.info.count, 2); XCTAssertEqualObjects(forwardEvent.info[@"af_success"], @"True"); - - [expectation fulfill]; } }]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; } - (void)testAttributeHashProjection { - XCTestExpectation *expectation = [self expectationWithDescription:@"Attribute hash projection"]; - [self setUserAttributesAndIdentities]; NSString *configurationStr = @"{ \ @@ -1935,7 +1845,6 @@ - (void)testAttributeHashProjection { MPEvent *event = [[MPEvent alloc] initWithName:@"test_string" type:MPEventTypeOther]; event.info = @{@"test_description":@"this is a description"}; - dispatch_async([MParticle messageQueue], ^{ [self->kitContainer forwardSDKCall:@selector(logEvent:) event:event messageType:MPMessageTypeEvent @@ -1947,13 +1856,8 @@ - (void)testAttributeHashProjection { XCTAssertNotNil(forwardEvent.info); XCTAssertEqual(forwardEvent.info.count, 1); XCTAssertEqualObjects(forwardEvent.info[@"af_description"], @"this is a description"); - - [expectation fulfill]; } }]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; } - (void)testAllocationAndDeallocation { @@ -1970,8 +1874,6 @@ - (void)testAllocationAndDeallocation { } - (void)testExpandedCommerceEventProjection { - XCTestExpectation *expectation = [self expectationWithDescription:@"Expanded commerce event projection"]; - [self setUserAttributesAndIdentities]; NSString *configurationStr = @"{ \ @@ -2044,17 +1946,12 @@ - (void)testExpandedCommerceEventProjection { MPProduct *product = [[MPProduct alloc] initWithName:@"product name" sku:@"product sku" quantity:@1 price:@45]; MPCommerceEvent *commerceEvent = [[MPCommerceEvent alloc] initWithAction:MPCommerceEventActionViewDetail product:product]; - dispatch_async([MParticle messageQueue], ^{ + [self->kitContainer forwardCommerceEventCall:commerceEvent kitHandler:^(id _Nonnull kit, MPKitFilter * _Nonnull kitFilter, MPKitExecStatus *__autoreleasing _Nonnull * _Nonnull execStatus) { if ([[[kit class] kitCode] isEqualToNumber:@(MPKitInstanceAppsFlyer)]) { XCTAssertEqualObjects(kitFilter.forwardEvent.name, @"af_content_view"); - - [expectation fulfill]; } }]; - }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; } - (void)testShouldDelayUploadMaxTime { diff --git a/UnitTests/MPURLRequestBuilderTests.m b/UnitTests/MPURLRequestBuilderTests.m index 0eb34d61..d439282c 100644 --- a/UnitTests/MPURLRequestBuilderTests.m +++ b/UnitTests/MPURLRequestBuilderTests.m @@ -11,6 +11,13 @@ #import "MPIUserDefaults.h" #import "MPPersistenceController.h" #import "MPMessage.h" +#import "MPKitInstanceValidator.h" + +@interface MPKitInstanceValidator () + ++ (void)includeUnitTestKits:(NSArray *)kitCodes; + +@end #pragma mark - MPURLRequestBuilder category @interface MPURLRequestBuilder(Tests) @@ -32,6 +39,8 @@ @implementation MPURLRequestBuilderTests - (void)setUp { [super setUp]; + [MPKitInstanceValidator includeUnitTestKits:@[@42]]; + MPStateMachine *stateMachine = [MPStateMachine sharedInstance]; stateMachine.apiKey = @"unit_test_app_key"; stateMachine.secret = @"unit_test_secret"; diff --git a/mParticle-Apple-SDK/AppNotifications/MPAppNotificationHandler.mm b/mParticle-Apple-SDK/AppNotifications/MPAppNotificationHandler.mm index 69eaf76e..504a96da 100644 --- a/mParticle-Apple-SDK/AppNotifications/MPAppNotificationHandler.mm +++ b/mParticle-Apple-SDK/AppNotifications/MPAppNotificationHandler.mm @@ -101,7 +101,7 @@ - (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { MPForwardQueueParameters *queueParameters = [[MPForwardQueueParameters alloc] init]; [queueParameters addParameter:error]; - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:failedRegistrationSelector parameters:queueParameters messageType:MPMessageTypeUnknown @@ -125,7 +125,7 @@ - (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { MPForwardQueueParameters *queueParameters = [[MPForwardQueueParameters alloc] init]; [queueParameters addParameter:deviceToken]; - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:deviceTokenSelector parameters:queueParameters messageType:MPMessageTypeUnknown @@ -148,7 +148,7 @@ - (void)didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notifi MPForwardQueueParameters *queueParameters = [[MPForwardQueueParameters alloc] init]; [queueParameters addParameter:notificationSettings]; - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:didRegisterUserNotificationSettingsSelector parameters:queueParameters messageType:MPMessageTypeUnknown @@ -171,7 +171,7 @@ - (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification: [queueParameters addParameter:identifier]; [queueParameters addParameter:userInfo]; - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:handleActionWithIdentifierSelector parameters:queueParameters messageType:MPMessageTypeUnknown @@ -195,7 +195,7 @@ - (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification: [queueParameters addParameter:userInfo]; [queueParameters addParameter:responseInfo]; - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:handleActionWithIdentifierSelector parameters:queueParameters messageType:MPMessageTypeUnknown @@ -220,9 +220,11 @@ - (void)receivedUserNotification:(NSDictionary *)userInfo actionIdentifier:(NSSt NSString *notificationName = userNotificationMode == MPUserNotificationModeRemote ? kMPRemoteNotificationReceivedNotification : kMPLocalNotificationReceivedNotification; - [[NSNotificationCenter defaultCenter] postNotificationName:notificationName - object:self - userInfo:userNotificationDictionary]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:notificationName + object:self + userInfo:userNotificationDictionary]; + }); if (!actionIdentifier) { @@ -231,7 +233,7 @@ - (void)receivedUserNotification:(NSDictionary *)userInfo actionIdentifier:(NSSt MPForwardQueueParameters *queueParameters = [[MPForwardQueueParameters alloc] init]; [queueParameters addParameter:userInfo]; - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:receivedNotificationSelector parameters:queueParameters messageType:MPMessageTypePushNotification @@ -253,7 +255,7 @@ - (void)didUpdateUserActivity:(nonnull NSUserActivity *)userActivity { MPForwardQueueParameters *queueParameters = [[MPForwardQueueParameters alloc] init]; [queueParameters addParameter:userActivity]; - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:didUpdateUserActivitySelector parameters:queueParameters messageType:MPMessageTypeUnknown @@ -273,18 +275,20 @@ - (void)userNotificationCenter:(nonnull UNUserNotificationCenter *)center willPr NSDictionary *userNotificationDictionary = @{kMPUserNotificationDictionaryKey:notification.request.content.userInfo, kMPUserNotificationRunningModeKey:@(self.runningMode)}; - [[NSNotificationCenter defaultCenter] postNotificationName:kMPRemoteNotificationReceivedNotification - object:self - userInfo:userNotificationDictionary]; - - SEL userNotificationCenterWillPresentNotification = @selector(userNotificationCenter:willPresentNotification:); - NSArray> *activeKitsRegistry = [[MPKitContainer sharedInstance] activeKitsRegistry]; - - for (id kitRegister in activeKitsRegistry) { - if ([kitRegister.wrapperInstance respondsToSelector:userNotificationCenterWillPresentNotification]) { - [kitRegister.wrapperInstance userNotificationCenter:center willPresentNotification:notification]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:kMPRemoteNotificationReceivedNotification + object:self + userInfo:userNotificationDictionary]; + + SEL userNotificationCenterWillPresentNotification = @selector(userNotificationCenter:willPresentNotification:); + NSArray> *activeKitsRegistry = [[MPKitContainer sharedInstance] activeKitsRegistry]; + + for (id kitRegister in activeKitsRegistry) { + if ([kitRegister.wrapperInstance respondsToSelector:userNotificationCenterWillPresentNotification]) { + [kitRegister.wrapperInstance userNotificationCenter:center willPresentNotification:notification]; + } } - } + }); } - (void)userNotificationCenter:(nonnull UNUserNotificationCenter *)center didReceiveNotificationResponse:(nonnull UNNotificationResponse *)response { @@ -299,32 +303,35 @@ - (void)userNotificationCenter:(nonnull UNUserNotificationCenter *)center didRec userNotificationDictionary[kMPUserNotificationActionKey] = response.actionIdentifier; } - [[NSNotificationCenter defaultCenter] postNotificationName:kMPRemoteNotificationReceivedNotification - object:self - userInfo:userNotificationDictionary]; - SEL userNotificationCenterDidReceiveNotificationResponse = @selector(userNotificationCenter:didReceiveNotificationResponse:); - NSArray> *activeKitsRegistry = [[MPKitContainer sharedInstance] activeKitsRegistry]; - NSNumber *lastKit = nil; - - for (id kitRegister in activeKitsRegistry) { - if ([kitRegister.wrapperInstance respondsToSelector:userNotificationCenterDidReceiveNotificationResponse]) { - MPKitExecStatus *execStatus = [kitRegister.wrapperInstance userNotificationCenter:center didReceiveNotificationResponse:response]; - - if (execStatus.success && ![lastKit isEqualToNumber:execStatus.kitCode]) { - lastKit = execStatus.kitCode; - - MPForwardRecord *forwardRecord = [[MPForwardRecord alloc] initWithMessageType:MPMessageTypePushNotification - execStatus:execStatus]; - - dispatch_async([MParticle messageQueue], ^{ - [[MPPersistenceController sharedInstance] saveForwardRecord:forwardRecord]; - }); + + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:kMPRemoteNotificationReceivedNotification + object:self + userInfo:userNotificationDictionary]; + + NSArray> *activeKitsRegistry = [[MPKitContainer sharedInstance] activeKitsRegistry]; + NSNumber *lastKit = nil; + + for (id kitRegister in activeKitsRegistry) { + if ([kitRegister.wrapperInstance respondsToSelector:userNotificationCenterDidReceiveNotificationResponse]) { + MPKitExecStatus *execStatus = [kitRegister.wrapperInstance userNotificationCenter:center didReceiveNotificationResponse:response]; - MPILogDebug(@"Forwarded user notifications call to kit: %@", kitRegister.name); + if (execStatus.success && ![lastKit isEqualToNumber:execStatus.kitCode]) { + lastKit = execStatus.kitCode; + + MPForwardRecord *forwardRecord = [[MPForwardRecord alloc] initWithMessageType:MPMessageTypePushNotification + execStatus:execStatus]; + + dispatch_async([MParticle messageQueue], ^{ + [[MPPersistenceController sharedInstance] saveForwardRecord:forwardRecord]; + }); + + MPILogDebug(@"Forwarded user notifications call to kit: %@", kitRegister.name); + } } } - } + }); } #endif @@ -342,7 +349,7 @@ - (BOOL)continueUserActivity:(nonnull NSUserActivity *)userActivity restorationH [queueParameters addParameter:userActivity]; [queueParameters addParameter:restorationHandler]; - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:continueUserActivitySelector parameters:queueParameters messageType:MPMessageTypeUnknown @@ -377,7 +384,7 @@ - (void)openURL:(NSURL *)url options:(NSDictionary *)options { [queueParameters addParameter:url]; [queueParameters addParameter:options]; - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:openURLOptionsSelector parameters:queueParameters messageType:MPMessageTypeUnknown @@ -404,7 +411,7 @@ - (void)openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication ann [queueParameters addParameter:sourceApplication]; [queueParameters addParameter:annotation]; - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:openURLSourceAppAnnotationSelector parameters:queueParameters messageType:MPMessageTypeUnknown diff --git a/mParticle-Apple-SDK/Identity/MPIdentityApi.m b/mParticle-Apple-SDK/Identity/MPIdentityApi.m index a8a5ba5b..c0f7ff61 100644 --- a/mParticle-Apple-SDK/Identity/MPIdentityApi.m +++ b/mParticle-Apple-SDK/Identity/MPIdentityApi.m @@ -86,12 +86,14 @@ - (void)onModifyRequestComplete:(MPIdentityApiRequest *)request httpResponse:(MP } // Forward call to kits - [[MPKitContainer sharedInstance] forwardIdentitySDKCall:@selector(onModifyComplete: request:) - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:self.currentUser kitConfiguration:kitConfig]; - FilteredMPIdentityApiRequest *filteredRequest = [[FilteredMPIdentityApiRequest alloc] initWithIdentityRequest:request kitConfiguration:kitConfig]; - [kit onModifyComplete:filteredUser request:filteredRequest]; - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] forwardIdentitySDKCall:@selector(onModifyComplete: request:) + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:self.currentUser kitConfiguration:kitConfig]; + FilteredMPIdentityApiRequest *filteredRequest = [[FilteredMPIdentityApiRequest alloc] initWithIdentityRequest:request kitConfiguration:kitConfig]; + [kit onModifyComplete:filteredUser request:filteredRequest]; + }]; + }); if (completion) { MPIdentityApiResult *apiResult = [[MPIdentityApiResult alloc] init]; @@ -164,57 +166,63 @@ - (void)onIdentityRequestComplete:(MPIdentityApiRequest *)request identityReques if (user) { NSDictionary *userInfo = @{mParticleUserKey:user}; - [[NSNotificationCenter defaultCenter] postNotificationName:mParticleIdentityStateChangeListenerNotification object:nil userInfo:userInfo]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:mParticleIdentityStateChangeListenerNotification object:nil userInfo:userInfo]; + }); } NSArray *kitConfig = [[MPKitContainer sharedInstance].originalConfig copy]; if (kitConfig) { - [[MPKitContainer sharedInstance] configureKits:kitConfig]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] configureKits:kitConfig]; + }); } // Forwarding calls to kits - switch (identityRequestType) { - case MPIdentityRequestIdentify: { - [[MPKitContainer sharedInstance] forwardIdentitySDKCall:@selector(onIdentifyComplete: request:) - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:user kitConfiguration:kitConfig]; - FilteredMPIdentityApiRequest *filteredRequest = [[FilteredMPIdentityApiRequest alloc] initWithIdentityRequest:request kitConfiguration:kitConfig]; - [kit onIdentifyComplete:filteredUser request:filteredRequest]; - }]; - break; - } - case MPIdentityRequestLogin: { - [[MPKitContainer sharedInstance] forwardIdentitySDKCall:@selector(onLoginComplete: request:) - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:user kitConfiguration:kitConfig]; - FilteredMPIdentityApiRequest *filteredRequest = [[FilteredMPIdentityApiRequest alloc] initWithIdentityRequest:request kitConfiguration:kitConfig]; - [kit onLoginComplete:filteredUser request:filteredRequest]; - }]; - break; - } - case MPIdentityRequestLogout: { - [[MPKitContainer sharedInstance] forwardIdentitySDKCall:@selector(onLogoutComplete: request:) - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:user kitConfiguration:kitConfig]; - FilteredMPIdentityApiRequest *filteredRequest = [[FilteredMPIdentityApiRequest alloc] initWithIdentityRequest:request kitConfiguration:kitConfig]; - [kit onLogoutComplete:filteredUser request:filteredRequest]; - }]; - break; - } - case MPIdentityRequestModify: { - [[MPKitContainer sharedInstance] forwardIdentitySDKCall:@selector(onModifyComplete: request:) - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:user kitConfiguration:kitConfig]; - FilteredMPIdentityApiRequest *filteredRequest = [[FilteredMPIdentityApiRequest alloc] initWithIdentityRequest:request kitConfiguration:kitConfig]; - [kit onModifyComplete:filteredUser request:filteredRequest]; - }]; - break; - } - default: { - MPILogError(@"Unknown identity request type: %@", @(identityRequestType)); - break; + dispatch_async(dispatch_get_main_queue(), ^{ + switch (identityRequestType) { + case MPIdentityRequestIdentify: { + [[MPKitContainer sharedInstance] forwardIdentitySDKCall:@selector(onIdentifyComplete: request:) + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:user kitConfiguration:kitConfig]; + FilteredMPIdentityApiRequest *filteredRequest = [[FilteredMPIdentityApiRequest alloc] initWithIdentityRequest:request kitConfiguration:kitConfig]; + [kit onIdentifyComplete:filteredUser request:filteredRequest]; + }]; + break; + } + case MPIdentityRequestLogin: { + [[MPKitContainer sharedInstance] forwardIdentitySDKCall:@selector(onLoginComplete: request:) + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:user kitConfiguration:kitConfig]; + FilteredMPIdentityApiRequest *filteredRequest = [[FilteredMPIdentityApiRequest alloc] initWithIdentityRequest:request kitConfiguration:kitConfig]; + [kit onLoginComplete:filteredUser request:filteredRequest]; + }]; + break; + } + case MPIdentityRequestLogout: { + [[MPKitContainer sharedInstance] forwardIdentitySDKCall:@selector(onLogoutComplete: request:) + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:user kitConfiguration:kitConfig]; + FilteredMPIdentityApiRequest *filteredRequest = [[FilteredMPIdentityApiRequest alloc] initWithIdentityRequest:request kitConfiguration:kitConfig]; + [kit onLogoutComplete:filteredUser request:filteredRequest]; + }]; + break; + } + case MPIdentityRequestModify: { + [[MPKitContainer sharedInstance] forwardIdentitySDKCall:@selector(onModifyComplete: request:) + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:user kitConfiguration:kitConfig]; + FilteredMPIdentityApiRequest *filteredRequest = [[FilteredMPIdentityApiRequest alloc] initWithIdentityRequest:request kitConfiguration:kitConfig]; + [kit onModifyComplete:filteredUser request:filteredRequest]; + }]; + break; + } + default: { + MPILogError(@"Unknown identity request type: %@", @(identityRequestType)); + break; + } } - } + }); if (completion) { completion(apiResult, nil); diff --git a/mParticle-Apple-SDK/Identity/MParticleUser.m b/mParticle-Apple-SDK/Identity/MParticleUser.m index 3d6049f0..ebba1e3f 100644 --- a/mParticle-Apple-SDK/Identity/MParticleUser.m +++ b/mParticle-Apple-SDK/Identity/MParticleUser.m @@ -22,6 +22,7 @@ @interface MParticleUser () @interface MParticle () + (dispatch_queue_t)messageQueue; ++ (dispatch_queue_t)networkQueue; @property (nonatomic, strong) MPBackendController *backendController; @end @@ -127,12 +128,14 @@ - (void)setUserIdentitySync:(NSString *)identityString identityType:(MPUserIdent MPILogDebug(@"Set user identity: %@", identityString); // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setUserIdentity:identityType:) - userIdentity:identityString - identityType:identityType - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - [kit setUserIdentity:identityString identityType:identityType]; - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setUserIdentity:identityType:) + userIdentity:identityString + identityType:identityType + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + [kit setUserIdentity:identityString identityType:identityType]; + }]; + }); } }]; } @@ -148,36 +151,37 @@ - (nullable NSNumber *)incrementUserAttribute:(NSString *)key byValue:(NSNumber NSNumber *newValue = [self.backendController incrementUserAttribute:key byValue:value]; MPILogDebug(@"User attribute %@ incremented by %@. New value: %@", key, value, newValue); - - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(incrementUserAttribute:byValue:) - userAttributeKey:key - value:value - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:self kitConfiguration:kitConfig]; - - if ([kit respondsToSelector:@selector(incrementUserAttribute:byValue:)]) { - [kit incrementUserAttribute:key byValue:value]; - } - if ([kit respondsToSelector:@selector(onIncrementUserAttribute:)] && filteredUser != nil) { - [kit onIncrementUserAttribute:filteredUser]; - } - }]; - - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setUserAttribute:value:) - userAttributeKey:key - value:newValue - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - if (![kit respondsToSelector:@selector(incrementUserAttribute:byValue:)]) { + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(incrementUserAttribute:byValue:) + userAttributeKey:key + value:value + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:self kitConfiguration:kitConfig]; - if ([kit respondsToSelector:@selector(setUserAttribute:value:)]) { - [kit setUserAttribute:key value:newValue]; + if ([kit respondsToSelector:@selector(incrementUserAttribute:byValue:)]) { + [kit incrementUserAttribute:key byValue:value]; + } + if ([kit respondsToSelector:@selector(onIncrementUserAttribute:)] && filteredUser != nil) { + [kit onIncrementUserAttribute:filteredUser]; } - if ([kit respondsToSelector:@selector(onSetUserAttribute:)] && filteredUser != nil) { - [kit onSetUserAttribute:filteredUser]; + }]; + + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setUserAttribute:value:) + userAttributeKey:key + value:newValue + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + if (![kit respondsToSelector:@selector(incrementUserAttribute:byValue:)]) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:self kitConfiguration:kitConfig]; + + if ([kit respondsToSelector:@selector(setUserAttribute:value:)]) { + [kit setUserAttribute:key value:newValue]; + } + if ([kit respondsToSelector:@selector(onSetUserAttribute:)] && filteredUser != nil) { + [kit onSetUserAttribute:filteredUser]; + } } - } - }]; + }]; + }); }); return @0; @@ -206,19 +210,20 @@ - (void)setUserAttribute:(nonnull NSString *)key value:(nonnull id)value { } else { MPILogDebug(@"Reset user attribute - %@", key); } - - // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setUserAttribute:value:) - userAttributeKey:key - value:value - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:strongSelf kitConfiguration:kitConfig]; - - [kit setUserAttribute:key value:value]; - if ([kit respondsToSelector:@selector(onSetUserAttribute:)] && filteredUser != nil) { - [kit onSetUserAttribute:filteredUser]; - } - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + // Forwarding calls to kits + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setUserAttribute:value:) + userAttributeKey:key + value:value + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:strongSelf kitConfiguration:kitConfig]; + + [kit setUserAttribute:key value:value]; + if ([kit respondsToSelector:@selector(onSetUserAttribute:)] && filteredUser != nil) { + [kit onSetUserAttribute:filteredUser]; + } + }]; + }); } }]; }); @@ -249,23 +254,25 @@ - (void)setUserAttributeList:(nonnull NSString *)key values:(nonnull NSArray kit, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:strongSelf kitConfiguration:kitConfig]; - if ([kit respondsToSelector:setUserAttributeListSelector]) { - [kit setUserAttribute:key values:values]; - } else if ([kit respondsToSelector:setUserAttributeSelector]) { - NSString *csvValues = [values componentsJoinedByString:@","]; - [kit setUserAttribute:key value:csvValues]; - } else if ([kit respondsToSelector:@selector(onSetUserAttribute:)] && filteredUser != nil) { - [kit onSetUserAttribute:filteredUser]; - } - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + SEL setUserAttributeSelector = @selector(setUserAttribute:value:); + SEL setUserAttributeListSelector = @selector(setUserAttribute:values:); + + [[MPKitContainer sharedInstance] forwardSDKCall:setUserAttributeListSelector + userAttributeKey:key + value:values + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:strongSelf kitConfiguration:kitConfig]; + if ([kit respondsToSelector:setUserAttributeListSelector]) { + [kit setUserAttribute:key values:values]; + } else if ([kit respondsToSelector:setUserAttributeSelector]) { + NSString *csvValues = [values componentsJoinedByString:@","]; + [kit setUserAttribute:key value:csvValues]; + } else if ([kit respondsToSelector:@selector(onSetUserAttribute:)] && filteredUser != nil) { + [kit onSetUserAttribute:filteredUser]; + } + }]; + }); } }]; }); @@ -285,17 +292,19 @@ - (void)setUserTag:(nonnull NSString *)tag { MPILogDebug(@"Set user tag - %@", tag); // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setUserTag:) - userAttributeKey:tag - value:nil - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:strongSelf kitConfiguration:kitConfig]; - - [kit setUserTag:tag]; - if ([kit respondsToSelector:@selector(onSetUserTag:)] && filteredUser != nil) { - [kit onSetUserTag:filteredUser]; - } - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setUserTag:) + userAttributeKey:tag + value:nil + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:strongSelf kitConfiguration:kitConfig]; + + [kit setUserTag:tag]; + if ([kit respondsToSelector:@selector(onSetUserTag:)] && filteredUser != nil) { + [kit onSetUserTag:filteredUser]; + } + }]; + }); } }]; }); @@ -315,17 +324,19 @@ - (void)removeUserAttribute:(nonnull NSString *)key { MPILogDebug(@"Removed user attribute - %@", key); // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:_cmd - userAttributeKey:key - value:nil - kitHandler:^(id kit, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:strongSelf kitConfiguration:kitConfig]; - - [kit removeUserAttribute:key]; - if ([kit respondsToSelector:@selector(onRemoveUserAttribute:)] && filteredUser != nil) { - [kit onRemoveUserAttribute:filteredUser]; - } - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] forwardSDKCall:_cmd + userAttributeKey:key + value:nil + kitHandler:^(id kit, MPKitConfiguration *kitConfig) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:strongSelf kitConfiguration:kitConfig]; + + [kit removeUserAttribute:key]; + if ([kit respondsToSelector:@selector(onRemoveUserAttribute:)] && filteredUser != nil) { + [kit onRemoveUserAttribute:filteredUser]; + } + }]; + }); } }]; }); @@ -334,23 +345,29 @@ - (void)removeUserAttribute:(nonnull NSString *)key { #pragma mark - User Segments - (void)userSegments:(NSTimeInterval)timeout endpointId:(NSString *)endpointId completionHandler:(MPUserSegmentsHandler)completionHandler { dispatch_async([MParticle messageQueue], ^{ - MPExecStatus execStatus = [self.backendController fetchSegments:timeout - endpointId:endpointId - completionHandler:^(NSArray *segments, NSTimeInterval elapsedTime, NSError *error) { - if (!segments) { - completionHandler(nil, error); - return; - } - - MPUserSegments *userSegments = [[MPUserSegments alloc] initWithSegments:segments]; - completionHandler(userSegments, error); - }]; - - if (execStatus == MPExecStatusSuccess) { - MPILogDebug(@"Fetching user segments"); - } else { - MPILogError(@"Could not fetch user segments: %@", [self.backendController execStatusDescription:execStatus]); - } + dispatch_async([MParticle networkQueue], ^{ + MPExecStatus execStatus = [self.backendController fetchSegments:timeout + endpointId:endpointId + completionHandler:^(NSArray *segments, NSTimeInterval elapsedTime, NSError *error) { + if (!segments) { + dispatch_async(dispatch_get_main_queue(), ^{ + completionHandler(nil, error); + }); + return; + } + + MPUserSegments *userSegments = [[MPUserSegments alloc] initWithSegments:segments]; + dispatch_async(dispatch_get_main_queue(), ^{ + completionHandler(userSegments, error); + }); + }]; + + if (execStatus == MPExecStatusSuccess) { + MPILogDebug(@"Fetching user segments"); + } else { + MPILogError(@"Could not fetch user segments: %@", [self.backendController execStatusDescription:execStatus]); + } + }); }); } @@ -362,11 +379,12 @@ - (void)setConsentState:(MPConsentState *)state { NSArray *kitConfig = [[MPKitContainer sharedInstance].originalConfig copy]; if (kitConfig) { - [[MPKitContainer sharedInstance] configureKits:kitConfig]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] configureKits:kitConfig]; + }); } - - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setConsentState:) consentState:state kitHandler:^(id _Nonnull kit, MPConsentState * _Nullable filteredConsentState, MPKitConfiguration * _Nonnull kitConfiguration) { MPKitExecStatus *status = [kit setConsentState:filteredConsentState]; if (!status.success) { diff --git a/mParticle-Apple-SDK/Kits/MPKitContainer.h b/mParticle-Apple-SDK/Kits/MPKitContainer.h index 6ed8469a..2ce6bfe0 100644 --- a/mParticle-Apple-SDK/Kits/MPKitContainer.h +++ b/mParticle-Apple-SDK/Kits/MPKitContainer.h @@ -24,7 +24,7 @@ - (nullable NSArray> *)activeKitsRegistry; - (void)configureKits:(nullable NSArray *)kitsConfiguration; - (nullable NSArray *)supportedKits; - +- (void)initializeKits; - (void)forwardCommerceEventCall:(nonnull MPCommerceEvent *)commerceEvent kitHandler:(void (^ _Nonnull)(id _Nonnull kit, MPKitFilter * _Nonnull kitFilter, MPKitExecStatus * _Nonnull * _Nonnull execStatus))kitHandler; - (void)forwardSDKCall:(nonnull SEL)selector event:(nullable MPEvent *)event messageType:(MPMessageType)messageType userInfo:(nullable NSDictionary *)userInfo kitHandler:(void (^ _Nonnull)(id _Nonnull kit, MPEvent * _Nullable forwardEvent, MPKitExecStatus * _Nonnull * _Nonnull execStatus))kitHandler; - (void)forwardSDKCall:(nonnull SEL)selector userAttributeKey:(nonnull NSString *)key value:(nullable id)value kitHandler:(void (^ _Nonnull)(id _Nonnull kit, MPKitConfiguration * _Nonnull kitConfiguration))kitHandler; diff --git a/mParticle-Apple-SDK/Kits/MPKitContainer.mm b/mParticle-Apple-SDK/Kits/MPKitContainer.mm index a3507b32..3239c12a 100644 --- a/mParticle-Apple-SDK/Kits/MPKitContainer.mm +++ b/mParticle-Apple-SDK/Kits/MPKitContainer.mm @@ -35,6 +35,7 @@ #import "mParticle.h" #import "MPConsentKitFilter.h" #import "MPIConstants.h" +#import "MPILogger.h" #define DEFAULT_ALLOCATION_FOR_KITS 2 @@ -95,10 +96,6 @@ - (instancetype)init { } } copy]; - if (![MPStateMachine sharedInstance].optOut) { - [self initializeKits]; - } - NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter addObserver:self selector:@selector(handleApplicationDidBecomeActive:) @@ -122,40 +119,44 @@ - (void)dealloc { #pragma mark Notification handlers - (void)handleApplicationDidBecomeActive:(NSNotification *)notification { - NSArray> *activeKitsRegistry = [self activeKitsRegistry]; - SEL didBecomeActiveSelector = @selector(didBecomeActive); - - for (idkitRegister in activeKitsRegistry) { - if ([kitRegister.wrapperInstance respondsToSelector:didBecomeActiveSelector]) { - [kitRegister.wrapperInstance didBecomeActive]; + dispatch_async(dispatch_get_main_queue(), ^{ + NSArray> *activeKitsRegistry = [self activeKitsRegistry]; + SEL didBecomeActiveSelector = @selector(didBecomeActive); + + for (idkitRegister in activeKitsRegistry) { + if ([kitRegister.wrapperInstance respondsToSelector:didBecomeActiveSelector]) { + [kitRegister.wrapperInstance didBecomeActive]; + } } - } + }); } - (void)handleApplicationDidFinishLaunching:(NSNotification *)notification { - MPStateMachine *stateMachine = [MPStateMachine sharedInstance]; - stateMachine.launchOptions = [notification userInfo]; - SEL launchOptionsSelector = @selector(setLaunchOptions:); - SEL startSelector = @selector(start); - - for (idkitRegister in kitsRegistry) { - id kitInstance = kitRegister.wrapperInstance; - - if (kitInstance && ![kitInstance started]) { - if ([kitInstance respondsToSelector:launchOptionsSelector]) { - [kitInstance setLaunchOptions:stateMachine.launchOptions]; - } + dispatch_async(dispatch_get_main_queue(), ^{ + MPStateMachine *stateMachine = [MPStateMachine sharedInstance]; + stateMachine.launchOptions = [notification userInfo]; + SEL launchOptionsSelector = @selector(setLaunchOptions:); + SEL startSelector = @selector(start); + + for (idkitRegister in kitsRegistry) { + id kitInstance = kitRegister.wrapperInstance; - if ([kitInstance respondsToSelector:startSelector]) { - @try { - [kitInstance start]; + if (kitInstance && ![kitInstance started]) { + if ([kitInstance respondsToSelector:launchOptionsSelector]) { + [kitInstance setLaunchOptions:stateMachine.launchOptions]; } - @catch (NSException *exception) { - MPILogError(@"Exception thrown while starting kit (%@): %@", kitInstance, exception); + + if ([kitInstance respondsToSelector:startSelector]) { + @try { + [kitInstance start]; + } + @catch (NSException *exception) { + MPILogError(@"Exception thrown while starting kit (%@): %@", kitInstance, exception); + } } } } - } + }); } #pragma mark Private accessors @@ -193,9 +194,11 @@ - (void)setKitsInitialized:(BOOL)kitsInitialized { } - (void)flushSerializedKits { - for (idkitRegister in kitsRegistry) { - [self freeKit:kitRegister.code]; - } + dispatch_async(dispatch_get_main_queue(), ^{ + for (idkitRegister in kitsRegistry) { + [self freeKit:kitRegister.code]; + } + }); } - (void)freeKit:(NSNumber *)kitCode { @@ -219,17 +222,18 @@ - (void)freeKit:(NSNumber *)kitCode { [fileManager removeItemAtPath:kitPath error:nil]; } - dispatch_async(dispatch_get_main_queue(), ^{ - NSDictionary *userInfo = @{mParticleKitInstanceKey:kitCode}; - - [[NSNotificationCenter defaultCenter] postNotificationName:mParticleKitDidBecomeInactiveNotification - object:nil - userInfo:userInfo]; - }); + NSDictionary *userInfo = @{mParticleKitInstanceKey:kitCode}; + + [[NSNotificationCenter defaultCenter] postNotificationName:mParticleKitDidBecomeInactiveNotification + object:nil + userInfo:userInfo]; } } - (void)initializeKits { + if (self.kitsInitialized) { + return; + } MPIUserDefaults *userDefaults = [MPIUserDefaults standardUserDefaults]; NSArray *directoryContents = [userDefaults getKitConfigurations]; @@ -241,24 +245,21 @@ - (void)initializeKits { self.kitsInitialized = YES; } - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - if ([MPStateMachine sharedInstance].logLevel >= MPILogLevelDebug) { - NSArray *supportedKits = [self supportedKits]; - - if (supportedKits.count > 0) { - NSMutableString *listOfKits = [[NSMutableString alloc] initWithString:@"Included kits: {"]; - for (NSNumber *supportedKit in supportedKits) { - [listOfKits appendFormat:@"%@, ", [self nameForKitCode:supportedKit]]; - } - - [listOfKits deleteCharactersInRange:NSMakeRange(listOfKits.length - 2, 2)]; - [listOfKits appendString:@"}"]; - - MPILogDebug(@"%@", listOfKits); + if ([MPStateMachine sharedInstance].logLevel >= MPILogLevelDebug) { + NSArray *supportedKits = [self supportedKits]; + + if (supportedKits.count > 0) { + NSMutableString *listOfKits = [[NSMutableString alloc] initWithString:@"Included kits: {"]; + for (NSNumber *supportedKit in supportedKits) { + [listOfKits appendFormat:@"%@, ", [self nameForKitCode:supportedKit]]; } + + [listOfKits deleteCharactersInRange:NSMakeRange(listOfKits.length - 2, 2)]; + [listOfKits appendString:@"}"]; + + MPILogDebug(@"%@", listOfKits); } - }); + } } - (NSDictionary *)methodMessageTypeMapping { @@ -300,21 +301,21 @@ - (void)replayQueuedItems { for (MPForwardQueueItem *forwardQueueItem in forwardQueueCopy) { switch (forwardQueueItem.queueItemType) { case MPQueueItemTypeEvent: { - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [self forwardSDKCall:forwardQueueItem.selector event:forwardQueueItem.event messageType:forwardQueueItem.messageType userInfo:nil kitHandler:forwardQueueItem.eventCompletionHandler]; }); break; } case MPQueueItemTypeEcommerce: { - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [self forwardCommerceEventCall:forwardQueueItem.commerceEvent kitHandler:forwardQueueItem.commerceEventCompletionHandler]; }); break; } case MPQueueItemTypeGeneralPurpose: { - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [self forwardSDKCall:forwardQueueItem.selector parameters:forwardQueueItem.queueParameters messageType:forwardQueueItem.messageType kitHandler:forwardQueueItem.generalPurposeCompletionHandler]; }); break; @@ -445,23 +446,15 @@ - (void)startKitRegister:(nonnull id)kitRegister configu configuration = [self validateAndTransformToSafeConfiguration:configuration]; if (configuration) { - dispatch_block_t kitBlock = ^{ - kitRegister.wrapperInstance = [[NSClassFromString(kitRegister.className) alloc] init]; - - MPKitAPI *kitApi = [[MPKitAPI alloc] initWithKitCode:kitRegister.code]; - if ([kitRegister.wrapperInstance respondsToSelector:@selector(setKitApi:)]) { - [kitRegister.wrapperInstance setKitApi:kitApi]; - } - - if ([kitRegister.wrapperInstance respondsToSelector:@selector(didFinishLaunchingWithConfiguration:)]) { - [kitRegister.wrapperInstance didFinishLaunchingWithConfiguration:configuration]; - } - }; + kitRegister.wrapperInstance = [[NSClassFromString(kitRegister.className) alloc] init]; - if ([NSThread isMainThread]) { - kitBlock(); - } else { - dispatch_sync(dispatch_get_main_queue(), kitBlock); + MPKitAPI *kitApi = [[MPKitAPI alloc] initWithKitCode:kitRegister.code]; + if ([kitRegister.wrapperInstance respondsToSelector:@selector(setKitApi:)]) { + [kitRegister.wrapperInstance setKitApi:kitApi]; + } + + if ([kitRegister.wrapperInstance respondsToSelector:@selector(didFinishLaunchingWithConfiguration:)]) { + [kitRegister.wrapperInstance didFinishLaunchingWithConfiguration:configuration]; } } } @@ -2083,44 +2076,45 @@ - (void)forwardCommerceEventCall:(MPCommerceEvent *)commerceEvent kitHandler:(vo return; } - - NSArray> *activeKitsRegistry = [self activeKitsRegistry]; - - for (idkitRegister in activeKitsRegistry) { - __block NSNumber *lastKit = nil; + dispatch_async(dispatch_get_main_queue(), ^{ + NSArray> *activeKitsRegistry = [self activeKitsRegistry]; - [self filter:kitRegister forCommerceEvent:commerceEvent completionHandler:^(MPKitFilter *kitFilter, BOOL finished) { - if (kitFilter.shouldFilter && !kitFilter.filteredAttributes) { - return; - } + for (idkitRegister in activeKitsRegistry) { + __block NSNumber *lastKit = nil; - if (kitFilter.forwardCommerceEvent || kitFilter.forwardEvent) { - __block MPKitExecStatus *execStatus = nil; - - dispatch_sync(dispatch_get_main_queue(), ^{ - @try { - kitHandler(kitRegister.wrapperInstance, kitFilter, &execStatus); - } @catch (NSException *e) { - MPILogError(@"Kit handler threw an exception: %@", e); - } - }); + [self filter:kitRegister forCommerceEvent:commerceEvent completionHandler:^(MPKitFilter *kitFilter, BOOL finished) { + if (kitFilter.shouldFilter && !kitFilter.filteredAttributes) { + return; + } - NSNumber *currentKit = kitRegister.code; - if (execStatus.success && ![lastKit isEqualToNumber:currentKit]) { - lastKit = currentKit; + if (kitFilter.forwardCommerceEvent || kitFilter.forwardEvent) { + __block MPKitExecStatus *execStatus = nil; - MPForwardRecord *forwardRecord = [[MPForwardRecord alloc] initWithMessageType:MPMessageTypeCommerceEvent - execStatus:execStatus - kitFilter:kitFilter - originalEvent:commerceEvent]; - [[MPPersistenceController sharedInstance] saveForwardRecord:forwardRecord]; + @try { + kitHandler(kitRegister.wrapperInstance, kitFilter, &execStatus); + } @catch (NSException *e) { + MPILogError(@"Kit handler threw an exception: %@", e); + } + - MPILogDebug(@"Forwarded logCommerceEvent call to kit: %@", kitRegister.name); + NSNumber *currentKit = kitRegister.code; + if (execStatus.success && ![lastKit isEqualToNumber:currentKit]) { + lastKit = currentKit; + + MPForwardRecord *forwardRecord = [[MPForwardRecord alloc] initWithMessageType:MPMessageTypeCommerceEvent + execStatus:execStatus + kitFilter:kitFilter + originalEvent:commerceEvent]; + dispatch_async([MParticle messageQueue], ^{ + [[MPPersistenceController sharedInstance] saveForwardRecord:forwardRecord]; + }); + MPILogDebug(@"Forwarded logCommerceEvent call to kit: %@", kitRegister.name); + } } - } - }]; - } + }]; + } + }); } - (void)forwardSDKCall:(SEL)selector event:(MPEvent *)event messageType:(MPMessageType)messageType userInfo:(NSDictionary *)userInfo kitHandler:(void (^)(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus))kitHandler { @@ -2132,6 +2126,7 @@ - (void)forwardSDKCall:(SEL)selector event:(MPEvent *)event messageType:(MPMessa MPForwardQueueItem *forwardQueueItem = [[MPForwardQueueItem alloc] initWithSelector:selector event:event messageType:messageType completionHandler:kitHandler]; if (forwardQueueItem) { + MPILogVerbose(@"Queueing event message for kits: %@", event); [self.forwardQueue addObject:forwardQueueItem]; } @@ -2150,17 +2145,16 @@ - (void)forwardSDKCall:(SEL)selector event:(MPEvent *)event messageType:(MPMessa if (kitFilter.forwardEvent) { __block MPKitExecStatus *execStatus = nil; - - dispatch_sync(dispatch_get_main_queue(), ^{ - @try { - kitHandler(kitRegister.wrapperInstance, kitFilter.forwardEvent, &execStatus); - } @catch (NSException *e) { - MPILogError(@"Kit handler threw an exception: %@", e); - } - }); + + @try { + MPILogDebug(@"Forwarding %@ call to kit: %@", NSStringFromSelector(selector), kitRegister.name); + kitHandler(kitRegister.wrapperInstance, kitFilter.forwardEvent, &execStatus); + } @catch (NSException *e) { + MPILogError(@"Kit handler threw an exception: %@", e); + } NSNumber *currentKit = kitRegister.code; - if (execStatus.success && ![lastKit isEqualToNumber:currentKit] && kitFilter.forwardEvent && messageType != MPMessageTypeUnknown) { + if (execStatus.success && ![lastKit isEqualToNumber:currentKit] && messageType != MPMessageTypeUnknown) { lastKit = currentKit; MPForwardRecord *forwardRecord = nil; @@ -2175,10 +2169,9 @@ - (void)forwardSDKCall:(SEL)selector event:(MPEvent *)event messageType:(MPMessa kitFilter:kitFilter originalEvent:event]; } - - [[MPPersistenceController sharedInstance] saveForwardRecord:forwardRecord]; - - MPILogDebug(@"Forwarded %@ call to kit: %@", NSStringFromSelector(selector), kitRegister.name); + dispatch_async([MParticle messageQueue], ^{ + [[MPPersistenceController sharedInstance] saveForwardRecord:forwardRecord]; + }); } } }; @@ -2216,13 +2209,11 @@ - (void)forwardSDKCall:(SEL)selector userAttributeKey:(NSString *)key value:(id) if (!kitFilter.shouldFilter) { MPKitConfiguration *kitConfiguration = self.kitConfigurations[kitRegister.code]; - dispatch_sync(dispatch_get_main_queue(), ^{ - @try { - kitHandler(kitRegister.wrapperInstance, kitConfiguration); - } @catch (NSException *e) { - MPILogError(@"Kit handler threw an exception: %@", e); - } - }); + @try { + kitHandler(kitRegister.wrapperInstance, kitConfiguration); + } @catch (NSException *e) { + MPILogError(@"Kit handler threw an exception: %@", e); + } MPILogDebug(@"Forwarded user attribute key: %@ value: %@ to kit: %@", key, value, kitRegister.name); } @@ -2238,13 +2229,12 @@ - (void)forwardSDKCall:(SEL)selector userAttributes:(NSDictionary *)userAttribut MPKitFilter *kitFilter = [self filter:kitRegister forUserAttributes:userAttributes]; MPKitConfiguration *kitConfiguration = self.kitConfigurations[kitRegister.code]; - dispatch_sync(dispatch_get_main_queue(), ^{ - @try { - kitHandler(kitRegister.wrapperInstance, kitFilter.filteredAttributes, kitConfiguration); - } @catch (NSException *e) { - MPILogError(@"Kit handler threw an exception: %@", e); - } - }); + + @try { + kitHandler(kitRegister.wrapperInstance, kitFilter.filteredAttributes, kitConfiguration); + } @catch (NSException *e) { + MPILogError(@"Kit handler threw an exception: %@", e); + } MPILogDebug(@"Forwarded user attributes to kit: %@", kitRegister.name); } @@ -2260,13 +2250,12 @@ - (void)forwardSDKCall:(SEL)selector userIdentity:(NSString *)identityString ide if (!kitFilter.shouldFilter) { MPKitConfiguration *kitConfiguration = self.kitConfigurations[kitRegister.code]; - dispatch_sync(dispatch_get_main_queue(), ^{ - @try { - kitHandler(kitRegister.wrapperInstance, kitConfiguration); - } @catch (NSException *e) { - MPILogError(@"Kit handler threw an exception: %@", e); - } - }); + + @try { + kitHandler(kitRegister.wrapperInstance, kitConfiguration); + } @catch (NSException *e) { + MPILogError(@"Kit handler threw an exception: %@", e); + } MPILogDebug(@"Forwarded setting user identity: %@ to kit: %@", identityString, kitRegister.name); } @@ -2282,13 +2271,12 @@ - (void)forwardSDKCall:(SEL)selector consentState:(MPConsentState *)state kitHan MPKitFilter *kitFilter = [self filter:kitRegister forConsentState:state]; if (!kitFilter.shouldFilter) { MPKitConfiguration *kitConfiguration = self.kitConfigurations[kitRegister.code]; - dispatch_sync(dispatch_get_main_queue(), ^{ - @try { - kitHandler(kitRegister.wrapperInstance, kitFilter.forwardConsentState, kitConfiguration); - } @catch (NSException *e) { - MPILogError(@"Kit handler threw an exception: %@", e); - } - }); + + @try { + kitHandler(kitRegister.wrapperInstance, kitFilter.forwardConsentState, kitConfiguration); + } @catch (NSException *e) { + MPILogError(@"Kit handler threw an exception: %@", e); + } MPILogDebug(@"Forwarded user attributes to kit: %@", kitRegister.name); } @@ -2305,16 +2293,13 @@ - (void)forwardSDKCall:(SEL)selector errorMessage:(NSString *)errorMessage excep if (!kitFilter.shouldFilter) { __block MPKitExecStatus *execStatus = nil; - - dispatch_sync(dispatch_get_main_queue(), ^{ - @try { - kitHandler(kitRegister.wrapperInstance, &execStatus); - } @catch (NSException *e) { - MPILogError(@"Kit handler threw an exception: %@", e); - } - }); - - MPILogDebug(@"Forwarded %@ call to kit: %@", NSStringFromSelector(selector), kitRegister.name); + + @try { + MPILogDebug(@"Forwarding %@ call to kit: %@", NSStringFromSelector(selector), kitRegister.name); + kitHandler(kitRegister.wrapperInstance, &execStatus); + } @catch (NSException *e) { + MPILogError(@"Kit handler threw an exception: %@", e); + } } } } @@ -2327,15 +2312,12 @@ - (void)forwardSDKCall:(SEL)selector kitHandler:(void (^)(id kit, if ([kitRegister.wrapperInstance respondsToSelector:selector]) { __block MPKitExecStatus *execStatus = nil; - dispatch_sync(dispatch_get_main_queue(), ^{ - @try { - kitHandler(kitRegister.wrapperInstance, &execStatus); - } @catch (NSException *e) { - MPILogError(@"Kit handler threw an exception: %@", e); - } - }); - - MPILogDebug(@"Forwarded %@ call to kit: %@", NSStringFromSelector(selector), kitRegister.name); + @try { + MPILogDebug(@"Forwarding %@ call to kit: %@", NSStringFromSelector(selector), kitRegister.name); + kitHandler(kitRegister.wrapperInstance, &execStatus); + } @catch (NSException *e) { + MPILogError(@"Kit handler threw an exception: %@", e); + } } } } @@ -2361,13 +2343,12 @@ - (void)forwardSDKCall:(SEL)selector parameters:(MPForwardQueueParameters *)para __block MPKitExecStatus *execStatus = nil; NSNumber *currentKit = kitRegister.code; - dispatch_sync(dispatch_get_main_queue(), ^{ - @try { - kitHandler(kitRegister.wrapperInstance, parameters, &execStatus); - } @catch (NSException *e) { - MPILogError(@"Kit handler threw an exception: %@", e); - } - }); + @try { + MPILogDebug(@"Forwarding %@ call to kit: %@", NSStringFromSelector(selector), kitRegister.name); + kitHandler(kitRegister.wrapperInstance, parameters, &execStatus); + } @catch (NSException *e) { + MPILogError(@"Kit handler threw an exception: %@", e); + } if (execStatus.success && ![lastKit isEqualToNumber:currentKit]) { lastKit = currentKit; @@ -2390,11 +2371,11 @@ - (void)forwardSDKCall:(SEL)selector parameters:(MPForwardQueueParameters *)para } if (forwardRecord) { - [[MPPersistenceController sharedInstance] saveForwardRecord:forwardRecord]; + dispatch_async([MParticle messageQueue], ^{ + [[MPPersistenceController sharedInstance] saveForwardRecord:forwardRecord]; + }); } } - - MPILogDebug(@"Forwarded %@ call to kit: %@", NSStringFromSelector(selector), kitRegister.name); } } @catch (NSException *exception) { MPILogError(@"An exception happened forwarding %@ to kit: %@\n reason: %@", NSStringFromSelector(selector), kitRegister.name, [exception reason]); @@ -2410,9 +2391,8 @@ - (void)forwardIdentitySDKCall:(SEL)selector kitHandler:(void (^)(id)delegate { self = [super init]; if (self) { messageQueue = [MParticle messageQueue]; + networkQueue = [MParticle networkQueue]; _sessionTimeout = DEFAULT_SESSION_TIMEOUT; nextCleanUpTime = [[NSDate date] timeIntervalSince1970]; backendBackgroundTaskIdentifier = UIBackgroundTaskInvalid; @@ -830,21 +833,26 @@ - (void)uploadOpenSessions:(NSMutableArray *)openSessions completionHandler:(voi __weak MPBackendController *weakSelf = self; - [self requestConfig:^(BOOL uploadBatch) { - if (!uploadBatch) { - invokeCompletionHandler(NO); - return; - } - - __strong MPBackendController *strongSelf = weakSelf; - - [strongSelf uploadBatchesWithCompletionHandler:^(BOOL success) { - session = nil; - - invokeCompletionHandler(success); - }]; - - }]; + dispatch_async(messageQueue, ^{ + dispatch_async(self->networkQueue, ^{ + [self requestConfig:^(BOOL uploadBatch) { + if (!uploadBatch) { + invokeCompletionHandler(NO); + return; + } + + __strong MPBackendController *strongSelf = weakSelf; + + [strongSelf uploadBatchesWithCompletionHandler:^(BOOL success) { + session = nil; + + invokeCompletionHandler(success); + }]; + + }]; + }); + }); + } #pragma mark Notification handlers @@ -891,11 +899,15 @@ - (void)handleApplicationDidEnterBackground:(NSNotification *)notification { [self saveMessage:message updateSession:MParticle.sharedInstance.automaticSessionTracking]; if (![MPStateMachine isAppExtension]) { - [self uploadDatabaseWithCompletionHandler:^{ - if (!MParticle.sharedInstance.automaticSessionTracking) { - [self endBackgroundTask]; - } - }]; + dispatch_async(self->networkQueue, ^{ + [self uploadDatabaseWithCompletionHandler:^{ + dispatch_async(dispatch_get_main_queue(), ^{ + if (!MParticle.sharedInstance.automaticSessionTracking) { + [self endBackgroundTask]; + } + }); + }]; + }); } else { [self endSession]; } @@ -922,7 +934,9 @@ - (void)handleApplicationWillEnterForeground:(NSNotification *)notification { #endif dispatch_async(messageQueue, ^{ - [self requestConfig:nil]; + dispatch_async(self->networkQueue, ^{ + [self requestConfig:nil]; + }); }); } @@ -1086,10 +1100,13 @@ - (void)beginBackgroundTimer { [strongSelf processOpenSessionsEndingCurrent:YES completionHandler:^(BOOL success) { - [MPStateMachine setRunningInBackground:NO]; + dispatch_async(dispatch_get_main_queue(), ^{ + [MPStateMachine setRunningInBackground:NO]; + + MPILogDebug(@"SDK has ended background activity."); + [strongSelf endBackgroundTask]; + }); - MPILogDebug(@"SDK has ended background activity."); - [strongSelf endBackgroundTask]; }]; } @@ -1128,12 +1145,13 @@ - (void)beginUploadTimer { strongSelf->uploadSource = [strongSelf createSourceTimer:strongSelf.uploadInterval eventHandler:^{ dispatch_async([MParticle messageQueue], ^{ - __strong MPBackendController *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - [strongSelf uploadDatabaseWithCompletionHandler:nil]; + dispatch_async(self->networkQueue, ^{ + __strong MPBackendController *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + [strongSelf uploadDatabaseWithCompletionHandler:nil]; + }); }); } cancelHandler:^{ @@ -1832,20 +1850,14 @@ - (void)startWithKey:(NSString *)apiKey secret:(NSString *)secret firstRun:(BOOL [MPPersistenceController setConsentState:consentState forMpid:[MPPersistenceController mpId]]; - dispatch_block_t startKitsBlock = ^{ - [MPKitContainer sharedInstance]; - MParticle.sharedInstance.identity.currentUser.consentState = consentState; - }; - - if (startKitsAsync) { + [MPKitContainer sharedInstance]; + if (![MPStateMachine sharedInstance].optOut) { dispatch_async(dispatch_get_main_queue(), ^{ - startKitsBlock(); + [[MPKitContainer sharedInstance] initializeKits]; }); - } else { - startKitsBlock(); } - - + MParticle.sharedInstance.identity.currentUser.consentState = consentState; + MPStateMachine *stateMachine = [MPStateMachine sharedInstance]; stateMachine.apiKey = apiKey; stateMachine.secret = secret; @@ -1877,13 +1889,17 @@ - (void)startWithKey:(NSString *)apiKey secret:(NSString *)secret firstRun:(BOOL [stateMachine.searchAttribution requestAttributionDetailsWithBlock:^{ [strongSelf processDidFinishLaunching:strongSelf->didFinishLaunchingNotification]; - [strongSelf uploadDatabaseWithCompletionHandler:nil]; + dispatch_async(self->networkQueue, ^{ + [strongSelf uploadDatabaseWithCompletionHandler:nil]; + }); }]; [strongSelf processPendingArchivedMessages]; [MPResponseConfig restore]; - [self requestConfig:nil]; + dispatch_async(self->networkQueue, ^{ + [self requestConfig:nil]; + }); MPILogDebug(@"SDK %@ has started", kMParticleSDKVersion); completionHandler(); @@ -1930,32 +1946,36 @@ - (void)saveMessage:(MPMessage *)message updateSession:(BOOL)updateSession { } if (shouldUpload) { - [self uploadDatabaseWithCompletionHandler:nil]; + dispatch_async(self->messageQueue, ^{ + dispatch_async(self->networkQueue, ^{ + [self uploadDatabaseWithCompletionHandler:nil]; + }); + }); } } - (MPExecStatus)uploadDatabaseWithCompletionHandler:(void (^ _Nullable)())completionHandler { __weak MPBackendController *weakSelf = self; - [self requestConfig:^(BOOL uploadBatch) { - __strong MPBackendController *strongSelf = weakSelf; - - BOOL shouldDelayUpload = [[MPKitContainer sharedInstance] shouldDelayUpload:kMPMaximumKitWaitTimeSeconds]; - if (!uploadBatch || shouldDelayUpload) { - if (completionHandler) { - completionHandler(); - } - - return; - } - - [strongSelf uploadBatchesWithCompletionHandler:^(BOOL success) { - if (completionHandler) { - completionHandler(); - } - }]; - - }]; + [self requestConfig:^(BOOL uploadBatch) { + __strong MPBackendController *strongSelf = weakSelf; + + BOOL shouldDelayUpload = [[MPKitContainer sharedInstance] shouldDelayUpload:kMPMaximumKitWaitTimeSeconds]; + if (!uploadBatch || shouldDelayUpload) { + if (completionHandler) { + completionHandler(); + } + + return; + } + + [strongSelf uploadBatchesWithCompletionHandler:^(BOOL success) { + if (completionHandler) { + completionHandler(); + } + }]; + + }]; return MPExecStatusSuccess; } diff --git a/mParticle-Apple-SDK/Utils/MPResponseConfig.m b/mParticle-Apple-SDK/Utils/MPResponseConfig.m index 88a18cc5..9e3d8585 100644 --- a/mParticle-Apple-SDK/Utils/MPResponseConfig.m +++ b/mParticle-Apple-SDK/Utils/MPResponseConfig.m @@ -74,7 +74,7 @@ - (nonnull instancetype)initWithConfiguration:(nonnull NSDictionary *)configurat BOOL shouldDefer = hasConsentFilters && !hasInitialIdentity; if (!shouldDefer) { - dispatch_sync(dispatch_get_main_queue(), ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] configureKits:self->_configuration[kMPRemoteConfigKitsKey]]; }); } else { diff --git a/mParticle-Apple-SDK/Utils/MPSearchAdsAttribution.m b/mParticle-Apple-SDK/Utils/MPSearchAdsAttribution.m index b29d3dee..0639399b 100644 --- a/mParticle-Apple-SDK/Utils/MPSearchAdsAttribution.m +++ b/mParticle-Apple-SDK/Utils/MPSearchAdsAttribution.m @@ -79,35 +79,37 @@ - (void)requestAttributionDetailsWithBlock:(void (^ _Nonnull)(void))completionHa void (^requestBlock)(void) = ^{ if (!called) { [MPClientSharedInstance performSelector:requestDetailsSelector withObject:^(NSDictionary *attributionDetails, NSError *error) { - ++numRequestsCompleted; - - __strong MPSearchAdsAttribution *strongSelf = weakSelf; - if (!strongSelf) { - return; - } - - if (!strongSelf.dictionary && attributionDetails && !error) { - NSDictionary* deepCopyDetails = nil; - @try { - deepCopyDetails = [NSKeyedUnarchiver unarchiveObjectWithData: - [NSKeyedArchiver archivedDataWithRootObject:attributionDetails]]; - } - @catch (NSException *e) { - deepCopyDetails = [attributionDetails copy]; - } + dispatch_async([MParticle messageQueue], ^{ + ++numRequestsCompleted; - if (deepCopyDetails) { - strongSelf.dictionary = deepCopyDetails; + __strong MPSearchAdsAttribution *strongSelf = weakSelf; + if (!strongSelf) { + return; } - onceCompletionBlock(); - } - else if (error.code == 1 /* ADClientErrorLimitAdTracking */) { - onceCompletionBlock(); - } - else if (numRequestsCompleted >= numRequests) { - onceCompletionBlock(); - } + if (!strongSelf.dictionary && attributionDetails && !error) { + NSDictionary* deepCopyDetails = nil; + @try { + deepCopyDetails = [NSKeyedUnarchiver unarchiveObjectWithData: + [NSKeyedArchiver archivedDataWithRootObject:attributionDetails]]; + } + @catch (NSException *e) { + deepCopyDetails = [attributionDetails copy]; + } + + if (deepCopyDetails) { + strongSelf.dictionary = deepCopyDetails; + } + + onceCompletionBlock(); + } + else if (error.code == 1 /* ADClientErrorLimitAdTracking */) { + onceCompletionBlock(); + } + else if (numRequestsCompleted >= numRequests) { + onceCompletionBlock(); + } + }); }]; } }; diff --git a/mParticle-Apple-SDK/mParticle.m b/mParticle-Apple-SDK/mParticle.m index 91156946..1116f8f7 100644 --- a/mParticle-Apple-SDK/mParticle.m +++ b/mParticle-Apple-SDK/mParticle.m @@ -34,6 +34,7 @@ #endif static dispatch_queue_t messageQueue = nil; +static dispatch_queue_t networkQueue = nil; static NSArray *eventTypeStrings = nil; NSString *const kMPEventNameLogTransaction = @"Purchase"; @@ -186,6 +187,10 @@ + (dispatch_queue_t)messageQueue { return messageQueue; } ++ (dispatch_queue_t)networkQueue { + return networkQueue; +} + - (instancetype)init { self = [super init]; if (!self) { @@ -193,6 +198,7 @@ - (instancetype)init { } messageQueue = dispatch_queue_create("com.mparticle.messageQueue", DISPATCH_QUEUE_SERIAL); + networkQueue = dispatch_queue_create("com.mparticle.networkQueue", DISPATCH_QUEUE_SERIAL); sdkInitialized = NO; privateOptOut = nil; isLoggingUncaughtExceptions = NO; @@ -269,16 +275,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N #pragma mark Notification handlers - (void)handleApplicationDidBecomeActive:(NSNotification *)notification { - dispatch_async([MParticle messageQueue], ^{ - NSDictionary *jailbrokenInfo = [MPDevice jailbrokenInfo]; - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setKitAttribute:value:) - event:nil - messageType:MPMessageTypeUnknown - userInfo:nil - kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { - *execStatus = [kit setKitAttribute:MPKitAttributeJailbrokenKey value:jailbrokenInfo]; - }]; - }); + } - (void)handleMemoryWarningNotification:(NSNotification *)notification { @@ -287,7 +284,7 @@ - (void)handleMemoryWarningNotification:(NSNotification *)notification { #pragma mark MPBackendControllerDelegate methods - (void)sessionDidBegin:(MPSession *)session { - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:@selector(beginSession) event:nil messageType:MPMessageTypeSessionStart @@ -299,7 +296,7 @@ - (void)sessionDidBegin:(MPSession *)session { } - (void)sessionDidEnd:(MPSession *)session { - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:@selector(endSession) event:nil messageType:MPMessageTypeSessionEnd @@ -312,7 +309,7 @@ - (void)sessionDidEnd:(MPSession *)session { #pragma mark MPBackendControllerDelegate methods - (void)forwardLogInstall { - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:_cmd event:nil messageType:MPMessageTypeUnknown @@ -324,7 +321,7 @@ - (void)forwardLogInstall { } - (void)forwardLogUpdate { - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:_cmd event:nil messageType:MPMessageTypeUnknown @@ -375,7 +372,7 @@ - (void)setConsoleLogging:(BOOL)consoleLogging { [MPStateMachine sharedInstance].consoleLogging = consoleLogging ? MPConsoleLoggingDisplay : MPConsoleLoggingSuppress; } - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setDebugMode:) event:nil messageType:MPMessageTypeUnknown @@ -410,7 +407,7 @@ - (void)setOptOut:(BOOL)optOut { _optOut = optOut; privateOptOut = @(optOut); - dispatch_async([MParticle messageQueue], ^{ + dispatch_async(dispatch_get_main_queue(), ^{ // Forwarding calls to kits [[MPKitContainer sharedInstance] forwardSDKCall:@selector(setOptOut:) event:nil @@ -604,7 +601,7 @@ - (void)startWithOptions:(MParticleOptions *)options { if (deferredKitConfiguration != nil && [deferredKitConfiguration isKindOfClass:[NSArray class]]) { - dispatch_sync(dispatch_get_main_queue(), ^{ + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] configureKits:deferredKitConfiguration]; weakSelf.deferredKitConfiguration = nil; }); @@ -653,9 +650,12 @@ - (void)startWithOptions:(MParticleOptions *)options { strongSelf.initialized = YES; - [[NSNotificationCenter defaultCenter] postNotificationName:mParticleDidFinishInitializing - object:self - userInfo:nil]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[NSNotificationCenter defaultCenter] postNotificationName:mParticleDidFinishInitializing + object:self + userInfo:nil]; + }); + }]; } @@ -779,11 +779,12 @@ - (nullable NSSet *)activeTimedEvents { - (void)beginTimedEvent:(MPEvent *)event { [self.backendController beginTimedEvent:event completionHandler:^(MPEvent *event, MPExecStatus execStatus) { - dispatch_async([MParticle messageQueue], ^{ - if (execStatus == MPExecStatusSuccess) { - MPILogDebug(@"Began timed event: %@", event); - - // Forwarding calls to kits + + if (execStatus == MPExecStatusSuccess) { + MPILogDebug(@"Began timed event: %@", event); + + // Forwarding calls to kits + dispatch_async(dispatch_get_main_queue(), ^{ [[MPKitContainer sharedInstance] forwardSDKCall:@selector(beginTimedEvent:) event:event messageType:MPMessageTypeEvent @@ -791,8 +792,8 @@ - (void)beginTimedEvent:(MPEvent *)event { kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { *execStatus = [kit beginTimedEvent:forwardEvent]; }]; - } - }); + }); + } }]; } @@ -803,26 +804,26 @@ - (void)endTimedEvent:(MPEvent *)event { completionHandler:^(MPEvent *event, MPExecStatus execStatus) { if (execStatus == MPExecStatusSuccess) { MPILogDebug(@"Ended and logged timed event: %@", event); - - // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(endTimedEvent:) - event:event - messageType:MPMessageTypeEvent - userInfo:nil - kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { - *execStatus = [kit endTimedEvent:forwardEvent]; - }]; - - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logEvent:) - event:event - messageType:MPMessageTypeEvent - userInfo:nil - kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { - if (![kit respondsToSelector:@selector(endTimedEvent:)]) { - *execStatus = [kit logEvent:forwardEvent]; - } - }]; - + dispatch_async(dispatch_get_main_queue(), ^{ + // Forwarding calls to kits + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(endTimedEvent:) + event:event + messageType:MPMessageTypeEvent + userInfo:nil + kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { + *execStatus = [kit endTimedEvent:forwardEvent]; + }]; + + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logEvent:) + event:event + messageType:MPMessageTypeEvent + userInfo:nil + kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { + if (![kit respondsToSelector:@selector(endTimedEvent:)]) { + *execStatus = [kit logEvent:forwardEvent]; + } + }]; + }); } }]; }); @@ -841,13 +842,15 @@ - (void)logEvent:(MPEvent *)event { MPILogDebug(@"Logged event: %@", event); // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logEvent:) - event:event - messageType:MPMessageTypeEvent - userInfo:nil - kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus *__autoreleasing *execStatus) { - *execStatus = [kit logEvent:forwardEvent]; - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logEvent:) + event:event + messageType:MPMessageTypeEvent + userInfo:nil + kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus *__autoreleasing *execStatus) { + *execStatus = [kit logEvent:forwardEvent]; + }]; + }); } }]; }); @@ -874,15 +877,16 @@ - (void)logScreenEvent:(MPEvent *)event { completionHandler:^(MPEvent *event, MPExecStatus execStatus) { if (execStatus == MPExecStatusSuccess) { MPILogDebug(@"Logged screen event: %@", event); - - // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logScreen:) - event:event - messageType:MPMessageTypeScreenView - userInfo:nil - kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { - *execStatus = [kit logScreen:forwardEvent]; - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + // Forwarding calls to kits + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logScreen:) + event:event + messageType:MPMessageTypeScreenView + userInfo:nil + kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { + *execStatus = [kit logScreen:forwardEvent]; + }]; + }); } }]; }); @@ -968,15 +972,16 @@ - (void)leaveBreadcrumb:(NSString *)breadcrumbName eventInfo:(NSDictionary kit, MPEvent *forwardEvent, MPKitExecStatus *__autoreleasing *execStatus) { - *execStatus = [kit leaveBreadcrumb:forwardEvent]; - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + // Forwarding calls to kits + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(leaveBreadcrumb:) + event:event + messageType:MPMessageTypeBreadcrumb + userInfo:nil + kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus *__autoreleasing *execStatus) { + *execStatus = [kit leaveBreadcrumb:forwardEvent]; + }]; + }); } }]; }); @@ -1002,13 +1007,15 @@ - (void)logError:(NSString *)message eventInfo:(NSDictionary *)e MPILogDebug(@"Logged error with message: %@", message); // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logError:eventInfo:) - errorMessage:message - exception:nil - eventInfo:eventInfo - kitHandler:^(id kit, MPKitExecStatus *__autoreleasing *execStatus) { - *execStatus = [kit logError:message eventInfo:eventInfo]; - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logError:eventInfo:) + errorMessage:message + exception:nil + eventInfo:eventInfo + kitHandler:^(id kit, MPKitExecStatus *__autoreleasing *execStatus) { + *execStatus = [kit logError:message eventInfo:eventInfo]; + }]; + }); } }]; }); @@ -1029,13 +1036,15 @@ - (void)logException:(NSException *)exception topmostContext:(id)topmostContext MPILogDebug(@"Logged exception name: %@, reason: %@, topmost context: %@", message, exception.reason, topmostContext); // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logError:eventInfo:) - errorMessage:nil - exception:exception - eventInfo:nil - kitHandler:^(id kit, MPKitExecStatus *__autoreleasing *execStatus) { - *execStatus = [kit logException:exception]; - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logError:eventInfo:) + errorMessage:nil + exception:exception + eventInfo:nil + kitHandler:^(id kit, MPKitExecStatus *__autoreleasing *execStatus) { + *execStatus = [kit logException:exception]; + }]; + }); } }]; }); @@ -1105,15 +1114,16 @@ - (void)logLTVIncrease:(double)increaseAmount eventName:(NSString *)eventName ev completionHandler:^(MPEvent *event, MPExecStatus execStatus) { if (execStatus == MPExecStatusSuccess) { MPILogDebug(@"Logged LTV Increase: %@", event); - - // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logLTVIncrease:event:) - event:nil - messageType:MPMessageTypeUnknown - userInfo:nil - kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { - *execStatus = [kit logLTVIncrease:increaseAmount event:forwardEvent]; - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + // Forwarding calls to kits + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(logLTVIncrease:event:) + event:nil + messageType:MPMessageTypeUnknown + userInfo:nil + kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { + *execStatus = [kit logLTVIncrease:increaseAmount event:forwardEvent]; + }]; + }); } }]; } @@ -1233,15 +1243,16 @@ - (CLLocation *)location { - (void)setLocation:(CLLocation *)location { [MPStateMachine sharedInstance].location = location; MPILogDebug(@"Set location %@", location); - - // Forwarding calls to kits - [[MPKitContainer sharedInstance] forwardSDKCall:_cmd - event:nil - messageType:MPMessageTypeEvent - userInfo:nil - kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { - *execStatus = [kit setLocation:location]; - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + // Forwarding calls to kits + [[MPKitContainer sharedInstance] forwardSDKCall:_cmd + event:nil + messageType:MPMessageTypeEvent + userInfo:nil + kitHandler:^(id kit, MPEvent *forwardEvent, MPKitExecStatus **execStatus) { + *execStatus = [kit setLocation:location]; + }]; + }); } - (void)beginLocationTracking:(CLLocationAccuracy)accuracy minDistance:(CLLocationDistance)distanceFilter { @@ -1363,13 +1374,14 @@ - (NSString *)surveyURL:(MPSurveyProvider)surveyProvider { } __block NSString *surveyURL = nil; - - [[MPKitContainer sharedInstance] forwardSDKCall:@selector(surveyURLWithUserAttributes:) - userAttributes:userAttributes - kitHandler:^(id kit, NSDictionary *forwardAttributes, MPKitConfiguration *kitConfig) { - FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:[[[MParticle sharedInstance] identity] currentUser] kitConfiguration:kitConfig]; - surveyURL = [kit surveyURLWithUserAttributes:filteredUser.userAttributes]; - }]; + dispatch_async(dispatch_get_main_queue(), ^{ + [[MPKitContainer sharedInstance] forwardSDKCall:@selector(surveyURLWithUserAttributes:) + userAttributes:userAttributes + kitHandler:^(id kit, NSDictionary *forwardAttributes, MPKitConfiguration *kitConfig) { + FilteredMParticleUser *filteredUser = [[FilteredMParticleUser alloc] initWithMParticleUser:[[[MParticle sharedInstance] identity] currentUser] kitConfiguration:kitConfig]; + surveyURL = [kit surveyURLWithUserAttributes:filteredUser.userAttributes]; + }]; + }); return surveyURL; } From f54bcc7d64ae5a05896bca113d7bc54afb121b60 Mon Sep 17 00:00:00 2001 From: mParticle Automation Date: Tue, 26 Jun 2018 10:43:35 -0400 Subject: [PATCH 19/21] Update version to 7.4.0 --- Framework/Info.plist | 2 +- mParticle-Apple-SDK.podspec | 2 +- mParticle-Apple-SDK/MPIConstants.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Info.plist b/Framework/Info.plist index fde8e5ff..b9380f8e 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 7.3.13 + 7.4.0 CFBundleSignature ???? CFBundleVersion diff --git a/mParticle-Apple-SDK.podspec b/mParticle-Apple-SDK.podspec index 6d8603cd..7e988f45 100644 --- a/mParticle-Apple-SDK.podspec +++ b/mParticle-Apple-SDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "mParticle-Apple-SDK" - s.version = "7.3.13" + s.version = "7.4.0" s.summary = "mParticle Apple SDK." s.description = <<-DESC diff --git a/mParticle-Apple-SDK/MPIConstants.m b/mParticle-Apple-SDK/MPIConstants.m index 4edfcb27..bb616aeb 100644 --- a/mParticle-Apple-SDK/MPIConstants.m +++ b/mParticle-Apple-SDK/MPIConstants.m @@ -1,7 +1,7 @@ #import "MPIConstants.h" // mParticle SDK Version -NSString *const kMParticleSDKVersion = @"7.3.13"; +NSString *const kMParticleSDKVersion = @"7.4.0"; // Message Type (dt) NSString *const kMPMessageTypeKey = @"dt"; From c69cd29120d5d776c928ece7e85bc565c91827a6 Mon Sep 17 00:00:00 2001 From: Peter Jenkins Date: Wed, 27 Jun 2018 15:41:14 -0400 Subject: [PATCH 20/21] Address possible crash when the app is terminating --- mParticle-Apple-SDK/MPBackendController.mm | 4 +++- mParticle-Apple-SDK/Persistence/MPPersistenceController.mm | 2 +- mParticle-Apple-SDK/mParticle.m | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mParticle-Apple-SDK/MPBackendController.mm b/mParticle-Apple-SDK/MPBackendController.mm index d027bfce..2ee3961d 100644 --- a/mParticle-Apple-SDK/MPBackendController.mm +++ b/mParticle-Apple-SDK/MPBackendController.mm @@ -945,7 +945,7 @@ - (void)handleApplicationDidFinishLaunching:(NSNotification *)notification { } - (void)handleApplicationWillTerminate:(NSNotification *)notification { - dispatch_async(messageQueue, ^{ + dispatch_sync(messageQueue, ^{ MPPersistenceController *persistence = [MPPersistenceController sharedInstance]; @@ -1018,6 +1018,8 @@ - (void)handleApplicationWillTerminate:(NSNotification *)notification { } }); + dispatch_suspend(messageQueue); + dispatch_suspend(networkQueue); } - (void)handleMemoryWarningNotification:(NSNotification *)notification { diff --git a/mParticle-Apple-SDK/Persistence/MPPersistenceController.mm b/mParticle-Apple-SDK/Persistence/MPPersistenceController.mm index 8ea95acf..82be7bb4 100644 --- a/mParticle-Apple-SDK/Persistence/MPPersistenceController.mm +++ b/mParticle-Apple-SDK/Persistence/MPPersistenceController.mm @@ -1624,7 +1624,7 @@ - (void)saveMessage:(MPMessage *)message { auxString = string([message.uuid UTF8String]); - sqlite3_bind_text(preparedStatement, 3, auxString.c_str(), (int)auxString.size(), SQLITE_STATIC); + sqlite3_bind_text(preparedStatement, 3, auxString.c_str(), (int)auxString.size(), SQLITE_TRANSIENT); sqlite3_bind_double(preparedStatement, 4, message.timestamp); sqlite3_bind_blob(preparedStatement, 5, [message.messageData bytes], (int)[message.messageData length], SQLITE_STATIC); diff --git a/mParticle-Apple-SDK/mParticle.m b/mParticle-Apple-SDK/mParticle.m index 1116f8f7..2e73f791 100644 --- a/mParticle-Apple-SDK/mParticle.m +++ b/mParticle-Apple-SDK/mParticle.m @@ -230,7 +230,6 @@ - (void)dealloc { NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter removeObserver:self name:UIApplicationDidBecomeActiveNotification object:nil]; [notificationCenter removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; - [notificationCenter removeObserver:self name:UIApplicationWillTerminateNotification object:nil]; } #pragma mark Private accessors From 634b205dc7312b1ee00695aeff083a1bba12fb6b Mon Sep 17 00:00:00 2001 From: mParticle Automation Date: Wed, 27 Jun 2018 15:55:01 -0400 Subject: [PATCH 21/21] Update version to 7.4.1 --- Framework/Info.plist | 2 +- mParticle-Apple-SDK.podspec | 2 +- mParticle-Apple-SDK/MPIConstants.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Framework/Info.plist b/Framework/Info.plist index b9380f8e..f16dd7fa 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 7.4.0 + 7.4.1 CFBundleSignature ???? CFBundleVersion diff --git a/mParticle-Apple-SDK.podspec b/mParticle-Apple-SDK.podspec index 7e988f45..0d21dda6 100644 --- a/mParticle-Apple-SDK.podspec +++ b/mParticle-Apple-SDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "mParticle-Apple-SDK" - s.version = "7.4.0" + s.version = "7.4.1" s.summary = "mParticle Apple SDK." s.description = <<-DESC diff --git a/mParticle-Apple-SDK/MPIConstants.m b/mParticle-Apple-SDK/MPIConstants.m index bb616aeb..46221229 100644 --- a/mParticle-Apple-SDK/MPIConstants.m +++ b/mParticle-Apple-SDK/MPIConstants.m @@ -1,7 +1,7 @@ #import "MPIConstants.h" // mParticle SDK Version -NSString *const kMParticleSDKVersion = @"7.4.0"; +NSString *const kMParticleSDKVersion = @"7.4.1"; // Message Type (dt) NSString *const kMPMessageTypeKey = @"dt";