From 3d72719706844984b9cf2c06f187ea5f65359e36 Mon Sep 17 00:00:00 2001 From: Aishwarya Nanna Date: Wed, 1 Feb 2023 21:00:47 +0530 Subject: [PATCH 01/20] Added public method 'enableLocation' to enable location in case of SPM --- CleverTapSDK/CTLocationManager.h | 4 ++-- CleverTapSDK/CTLocationManager.m | 8 ++++---- CleverTapSDK/CleverTap.h | 11 +++++++++++ CleverTapSDK/CleverTap.m | 21 ++++++++++++++++++++- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/CleverTapSDK/CTLocationManager.h b/CleverTapSDK/CTLocationManager.h index 4c9b1cc5..b95c71d9 100644 --- a/CleverTapSDK/CTLocationManager.h +++ b/CleverTapSDK/CTLocationManager.h @@ -3,8 +3,8 @@ @interface CTLocationManager : NSObject -#if defined(CLEVERTAP_LOCATION) +//#if defined(CLEVERTAP_LOCATION) + (void)getLocationWithSuccess:(void (^)(CLLocationCoordinate2D location))success andError:(void (^)(NSString *reason))error; -#endif +//#endif @end diff --git a/CleverTapSDK/CTLocationManager.m b/CleverTapSDK/CTLocationManager.m index 5f89a2a3..b50c81e2 100644 --- a/CleverTapSDK/CTLocationManager.m +++ b/CleverTapSDK/CTLocationManager.m @@ -13,7 +13,7 @@ @interface CleverTapLocationRequest : NSObject @implementation CleverTapLocationRequest @end -#if defined(CLEVERTAP_LOCATION) +//#if defined(CLEVERTAP_LOCATION) NSString *const kLocationTimeoutError = @"Location Request Timed Out: Have You Set NSLocationWhenInUseUsageDescription in Your Info.plist?"; NSString *const kLocationServicesNotEnabled = @"Location Services Not Enabled"; NSString *const kLocationPermissionDenied = @"Location Permission Denied"; @@ -26,11 +26,11 @@ @implementation CleverTapLocationRequest static NSMutableArray *pendingRequests; static NSObject *requestsLockObject; -#endif +//#endif @implementation CTLocationManager -#if defined(CLEVERTAP_LOCATION) +//#if defined(CLEVERTAP_LOCATION) /** NOTE: If NSLocationWhenInUseUsageDescription is not set in the app's Info.plist, calls to the CLLocationManager instance will fail silently. Rely on the location timeout to stop updating and return an error in this case. */ @@ -201,6 +201,6 @@ + (void)stopUpdatingLocation { locationManager.delegate = nil; [self cancelLocationTimeout]; } -#endif +//#endif @end diff --git a/CleverTapSDK/CleverTap.h b/CleverTapSDK/CleverTap.h index f824a8ed..1f884a8d 100644 --- a/CleverTapSDK/CleverTap.h +++ b/CleverTapSDK/CleverTap.h @@ -354,6 +354,17 @@ typedef NS_ENUM(int, CTSignedCallEvent) { */ extern NSString * _Nonnull const CleverTapGeofencesDidUpdateNotification; +/*! + @method + + @abstract + Enables the location API + + @discussion + Call this method (typically once at app launch) to enable the location API. + + */ ++ (void)enableLocation:(BOOL)enabled; /*! @method diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index 370bb1b6..4f2df73e 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -250,6 +250,8 @@ @interface CleverTap () { @property (atomic, assign) BOOL geofenceLocation; @property (nonatomic, strong) NSString *gfSDKVersion; +@property (atomic, assign) BOOL isLocationEnabled; + - (instancetype)init __unavailable; @end @@ -4078,11 +4080,28 @@ - (BOOL)geofenceLocation { return _geofenceLocation; } ++ (void)enableLocation:(BOOL)enabled{ + [[self sharedInstance] setLocationEnabled:enabled]; +} + +- (void)setLocationEnabled:(BOOL)enabled { + _isLocationEnabled = enabled; +} + +- (BOOL)getIsLocationEnabled { + return _isLocationEnabled; +} + + (void)getLocationWithSuccess:(void (^)(CLLocationCoordinate2D location))success andError:(void (^)(NSString *reason))error; { #if defined(CLEVERTAP_LOCATION) [CTLocationManager getLocationWithSuccess:success andError:error]; #else - CleverTapLogStaticInfo(@"To Enable CleverTap Location services/apis please build the SDK with the CLEVERTAP_LOCATION macro"); + if ([[self sharedInstance] getIsLocationEnabled]){ + [CTLocationManager getLocationWithSuccess:success andError:error]; + + }else{ + CleverTapLogStaticInfo(@"To Enable CleverTap Location services/apis please build the SDK with the CLEVERTAP_LOCATION macro"); + } #endif } From b69d497031031460895ba5103b009e9f496715bb Mon Sep 17 00:00:00 2001 From: Aishwarya Nanna Date: Thu, 2 Feb 2023 11:38:12 +0530 Subject: [PATCH 02/20] log for location enable --- CleverTapSDK/CleverTap.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index 4f2df73e..9438a43e 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -4100,7 +4100,7 @@ + (void)getLocationWithSuccess:(void (^)(CLLocationCoordinate2D location))succes [CTLocationManager getLocationWithSuccess:success andError:error]; }else{ - CleverTapLogStaticInfo(@"To Enable CleverTap Location services/apis please build the SDK with the CLEVERTAP_LOCATION macro"); + CleverTapLogStaticInfo(@"To Enable CleverTap Location services/apis please build the SDK with the CLEVERTAP_LOCATION macro or use enableLocation method"); } #endif } From b6def444ee2c022b71f97678615337ecfde9ccc4 Mon Sep 17 00:00:00 2001 From: Aishwarya Nanna Date: Fri, 3 Feb 2023 16:14:29 +0530 Subject: [PATCH 03/20] Added public API for marking app inbox messages as read in bulk --- CleverTapSDK/CleverTap+Inbox.h | 9 +++++++++ CleverTapSDK/CleverTap.m | 7 +++++++ CleverTapSDK/Inbox/controllers/CTInboxController.h | 1 + CleverTapSDK/Inbox/controllers/CTInboxController.m | 13 +++++++++++++ 4 files changed, 30 insertions(+) diff --git a/CleverTapSDK/CleverTap+Inbox.h b/CleverTapSDK/CleverTap+Inbox.h index 10da6a14..1051b33f 100755 --- a/CleverTapSDK/CleverTap+Inbox.h +++ b/CleverTapSDK/CleverTap+Inbox.h @@ -203,6 +203,15 @@ typedef void (^CleverTapInboxUpdatedBlock)(void); - (void)markReadInboxMessageForID:(NSString * _Nonnull)messageId; +/*! + @method + + @abstract + This method marks the `CleverTapInboxMessage` object as read for given 'Message Ids` as Collection. + */ + +- (void)markReadInboxMessagesForIDs:(NSArray *_Nonnull)messageIds; + /*! @method diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index 9438a43e..0a485872 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -4373,6 +4373,13 @@ - (void)markReadInboxMessageForID:(NSString *)messageId{ [self.inboxController markReadMessageWithId:messageId]; } +- (void)markReadInboxMessagesForIDs:(NSArray *_Nonnull)messageIds{ + if (![self _isInboxInitialized]) { + return; + } + [self.inboxController markReadMessagesWithId:messageIds]; +} + - (void)registerInboxUpdatedBlock:(CleverTapInboxUpdatedBlock)block { if (!_inboxUpdateBlocks) { _inboxUpdateBlocks = [NSMutableArray new]; diff --git a/CleverTapSDK/Inbox/controllers/CTInboxController.h b/CleverTapSDK/Inbox/controllers/CTInboxController.h index 5c560ba4..c4d8a832 100755 --- a/CleverTapSDK/Inbox/controllers/CTInboxController.h +++ b/CleverTapSDK/Inbox/controllers/CTInboxController.h @@ -29,6 +29,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)deleteMessageWithId:(NSString *)messageId; - (void)deleteMessagesWithId:(NSArray *_Nonnull)messageIds; - (void)markReadMessageWithId:(NSString *)messageId; +- (void)markReadMessagesWithId:(NSArray *_Nonnull)messageIds; @end diff --git a/CleverTapSDK/Inbox/controllers/CTInboxController.m b/CleverTapSDK/Inbox/controllers/CTInboxController.m index aad25225..75562435 100755 --- a/CleverTapSDK/Inbox/controllers/CTInboxController.m +++ b/CleverTapSDK/Inbox/controllers/CTInboxController.m @@ -122,6 +122,19 @@ - (void)markReadMessageWithId:(NSString *)messageId { }]; } +- (void)markReadMessagesWithId:(NSArray *_Nonnull)messageIds { + [privateContext performBlock:^{ + for (NSString *ids in messageIds) { + CTMessageMO *message = [self _messageForId:ids]; + if (message) { + [message setValue:@YES forKey:@"isRead"]; + } + } + [self _save]; + [self notifyUpdate]; + }]; +} + - (NSDictionary *)messageForId:(NSString *)messageId { if (!self.isInitialized) return nil; CTMessageMO *msg = [self _messageForId:messageId]; From 9ab7aa94bc85fca53459649a3985c0b0d8b1807f Mon Sep 17 00:00:00 2001 From: Aishwarya Nanna Date: Fri, 3 Feb 2023 16:47:51 +0530 Subject: [PATCH 04/20] -Updated changelog, podspec and buildinfo files. --- CHANGELOG.md | 6 ++++++ CleverTap-iOS-SDK.podspec | 2 +- CleverTapSDK/CleverTapBuildInfo.h | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a056363..805dba2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Change Log All notable changes to this project will be documented in this file. +### [Version 4.2.1](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/4.2.1) (February 03, 2023) + +#### Added +- Adds a new `enableLocation` API for enabling location in case of SPM. +- Adds a public instance method `markReadInboxMessagesForIDs` for marking multiple App Inbox messages as read by passing a collection of `messageID`s. + ### [Version 4.2.0](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/4.2.0) (December 13, 2022) #### Added diff --git a/CleverTap-iOS-SDK.podspec b/CleverTap-iOS-SDK.podspec index b3d176dc..5dadcf72 100644 --- a/CleverTap-iOS-SDK.podspec +++ b/CleverTap-iOS-SDK.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "CleverTap-iOS-SDK" -s.version = "4.2.0" +s.version = "4.2.1" s.summary = "The CleverTap iOS SDK for App Analytics and Engagement." s.homepage = "https://github.com/CleverTap/clevertap-ios-sdk" s.license = { :type => "MIT" } diff --git a/CleverTapSDK/CleverTapBuildInfo.h b/CleverTapSDK/CleverTapBuildInfo.h index ef2f044d..a4098590 100644 --- a/CleverTapSDK/CleverTapBuildInfo.h +++ b/CleverTapSDK/CleverTapBuildInfo.h @@ -1,3 +1,3 @@ -#define WR_SDK_REVISION @"40200" +#define WR_SDK_REVISION @"40201" From 23f2d9d4150f7df8f485e8a5b77136ef83b95dda Mon Sep 17 00:00:00 2001 From: kushagraa14 Date: Fri, 3 Mar 2023 11:17:26 +0530 Subject: [PATCH 05/20] Add hotfix for deleteInboxMessageForID crash when message ID is null or invalid --- CleverTapSDK/Inbox/controllers/CTInboxController.m | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/CleverTapSDK/Inbox/controllers/CTInboxController.m b/CleverTapSDK/Inbox/controllers/CTInboxController.m index aad25225..2d684d89 100755 --- a/CleverTapSDK/Inbox/controllers/CTInboxController.m +++ b/CleverTapSDK/Inbox/controllers/CTInboxController.m @@ -103,9 +103,19 @@ - (void)deleteMessageWithId:(NSString *)messageId { - (void)deleteMessagesWithId:(NSArray *_Nonnull)messageIds { NSMutableArray *toDeleteInboxMessages = [NSMutableArray new]; for (NSString *ids in messageIds) { - CTMessageMO *msg = [self _messageForId:ids]; - [toDeleteInboxMessages addObject:msg]; + if (ids != nil && ![ids isEqualToString:@""]){ + CTMessageMO *msg = [self _messageForId:ids]; + if (msg) { + [toDeleteInboxMessages addObject:msg]; + } + else { + NSLog(@"%@ is invalid App-inbox ID", ids); + } } + else { + NSLog(@"App Inbox ID is null or not a string"); + } + } if ([toDeleteInboxMessages count] > 0) { [self _deleteMessages:toDeleteInboxMessages]; } From 406be9c52a25a99aafa5b60dc7c7db2ad6ad21b1 Mon Sep 17 00:00:00 2001 From: Akash Malhotra Date: Fri, 3 Mar 2023 15:12:22 +0530 Subject: [PATCH 06/20] fixed a bug where CoreData would crash with threading inconsistency exceptions --- .../Inbox/controllers/CTInboxController.m | 108 +++++++++++------- 1 file changed, 68 insertions(+), 40 deletions(-) diff --git a/CleverTapSDK/Inbox/controllers/CTInboxController.m b/CleverTapSDK/Inbox/controllers/CTInboxController.m index aad25225..489ace28 100755 --- a/CleverTapSDK/Inbox/controllers/CTInboxController.m +++ b/CleverTapSDK/Inbox/controllers/CTInboxController.m @@ -150,21 +150,24 @@ - (NSInteger)unreadCount { BOOL hasMessages = ([[self.user.entity propertiesByName] objectForKey:@"messages"] != nil); if (!hasMessages) return nil; - for (CTMessageMO *msg in self.user.messages) { - int ttl = (int)msg.expires; - if (ttl > 0 && now >= ttl) { - CleverTapLogStaticInternal(@"%@: message expires: %@, deleting", self, msg); - [toDelete addObject:msg]; - } else { - [messages addObject:[msg toJSON]]; + [privateContext performBlockAndWait:^{ + for (CTMessageMO *msg in self.user.messages) { + int ttl = (int)msg.expires; + if (ttl > 0 && now >= ttl) { + CleverTapLogStaticInternal(@"%@: message expires: %@, deleting", self, msg); + [toDelete addObject:msg]; + } else { + [messages addObject:[msg toJSON]]; + } } - } - NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO]; - [messages sortUsingDescriptors:@[sortDescriptor]]; - - if ([toDelete count] > 0) { - [self _deleteMessages:toDelete]; - } + NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO]; + [messages sortUsingDescriptors:@[sortDescriptor]]; + + if ([toDelete count] > 0) { + [self _deleteMessages:toDelete]; + } + + }]; return messages; } @@ -177,22 +180,26 @@ - (NSInteger)unreadCount { BOOL hasMessages = ([[self.user.entity propertiesByName] objectForKey:@"messages"] != nil); if (!hasMessages) return nil; - NSOrderedSet *results = [self.user.messages filteredOrderedSetUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"isRead == NO"]]]; - for (CTMessageMO *msg in results) { - int ttl = (int)msg.expires; - if (ttl > 0 && now >= ttl) { - CleverTapLogStaticInternal(@"%@: message expires: %@, deleting", self, msg); - [toDelete addObject:msg]; - } else { - [messages addObject:[msg toJSON]]; + [privateContext performBlockAndWait:^{ + NSOrderedSet *results = [self.user.messages filteredOrderedSetUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"isRead == NO"]]]; + for (CTMessageMO *msg in results) { + int ttl = (int)msg.expires; + if (ttl > 0 && now >= ttl) { + CleverTapLogStaticInternal(@"%@: message expires: %@, deleting", self, msg); + [toDelete addObject:msg]; + } else { + [messages addObject:[msg toJSON]]; + } } - } - NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO]; - [messages sortUsingDescriptors:@[sortDescriptor]]; + NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO]; + [messages sortUsingDescriptors:@[sortDescriptor]]; + + if ([toDelete count] > 0) { + [self _deleteMessages:toDelete]; + } + }]; + - if ([toDelete count] > 0) { - [self _deleteMessages:toDelete]; - } return messages; } @@ -204,8 +211,12 @@ - (CTMessageMO *)_messageForId:(NSString *)messageId { BOOL hasMessages = ([[self.user.entity propertiesByName] objectForKey:@"messages"] != nil); if (!hasMessages) return nil; - - NSOrderedSet *results = [self.user.messages filteredOrderedSetUsingPredicate:[NSPredicate predicateWithFormat:@"id == %@", messageId]]; + __block NSOrderedSet *results; + + [privateContext performBlockAndWait:^{ + results = [self.user.messages filteredOrderedSetUsingPredicate:[NSPredicate predicateWithFormat:@"id == %@", messageId]]; + }]; + BOOL existing = results && [results count] > 0; return existing ? results[0] : nil; } @@ -222,16 +233,33 @@ - (void)_deleteMessages:(NSArray*)messages { // always call from inside privateContext performBlock - (BOOL)_save { - NSError *error = nil; - BOOL res = YES; - res = [privateContext save:&error]; - if (!res) { - CleverTapLogStaticDebug(@"Error saving core data private context: %@\n%@", [error localizedDescription], [error userInfo]); - } - res = [mainContext save:&error]; - if (!res) { - CleverTapLogStaticDebug(@"Error saving core data main context: %@\n%@", [error localizedDescription], [error userInfo]); - } +// NSError *error = nil; + __block BOOL res = YES; +// res = [privateContext save:&error]; +// if (!res) { +// CleverTapLogStaticDebug(@"Error saving core data private context: %@\n%@", [error localizedDescription], [error userInfo]); +// } + [privateContext performBlockAndWait:^{ + NSError *error = nil; + res = [privateContext save:&error]; + if (!res) { + CleverTapLogStaticDebug(@"Error saving core data main context: %@\n%@", [error localizedDescription], [error userInfo]); + } + }]; +// dispatch_async(dispatch_get_main_queue(), ^{ +// NSError *errorr = nil; +// res = [mainContext save:&errorr]; +// if (!res) { +// CleverTapLogStaticDebug(@"Error saving core data main context: %@\n%@", [error localizedDescription], [error userInfo]); +// } +// }); + [mainContext performBlockAndWait:^{ + NSError *error = nil; + res = [mainContext save:&error]; + if (!res) { + CleverTapLogStaticDebug(@"Error saving core data main context: %@\n%@", [error localizedDescription], [error userInfo]); + } + }]; return res; } From e184c3c93591e2e10545b6341214d66bc2b49cfc Mon Sep 17 00:00:00 2001 From: Akash Malhotra Date: Tue, 7 Mar 2023 09:40:45 +0530 Subject: [PATCH 07/20] removed comments --- CleverTapSDK/Inbox/controllers/CTInboxController.m | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/CleverTapSDK/Inbox/controllers/CTInboxController.m b/CleverTapSDK/Inbox/controllers/CTInboxController.m index 489ace28..3a068f3e 100755 --- a/CleverTapSDK/Inbox/controllers/CTInboxController.m +++ b/CleverTapSDK/Inbox/controllers/CTInboxController.m @@ -233,12 +233,7 @@ - (void)_deleteMessages:(NSArray*)messages { // always call from inside privateContext performBlock - (BOOL)_save { -// NSError *error = nil; __block BOOL res = YES; -// res = [privateContext save:&error]; -// if (!res) { -// CleverTapLogStaticDebug(@"Error saving core data private context: %@\n%@", [error localizedDescription], [error userInfo]); -// } [privateContext performBlockAndWait:^{ NSError *error = nil; res = [privateContext save:&error]; @@ -246,13 +241,6 @@ - (BOOL)_save { CleverTapLogStaticDebug(@"Error saving core data main context: %@\n%@", [error localizedDescription], [error userInfo]); } }]; -// dispatch_async(dispatch_get_main_queue(), ^{ -// NSError *errorr = nil; -// res = [mainContext save:&errorr]; -// if (!res) { -// CleverTapLogStaticDebug(@"Error saving core data main context: %@\n%@", [error localizedDescription], [error userInfo]); -// } -// }); [mainContext performBlockAndWait:^{ NSError *error = nil; res = [mainContext save:&error]; From 521689b5962e160184eb236c826a1231afbb977d Mon Sep 17 00:00:00 2001 From: Aishwarya Nanna Date: Mon, 20 Mar 2023 16:33:38 +0530 Subject: [PATCH 08/20] -Added public API method 'dismissAppInbox' to dismiss CleverTapInboxViewController. --- CleverTapSDK/CleverTap+Inbox.h | 7 +++++++ CleverTapSDK/CleverTap.m | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/CleverTapSDK/CleverTap+Inbox.h b/CleverTapSDK/CleverTap+Inbox.h index 10da6a14..220158a6 100755 --- a/CleverTapSDK/CleverTap+Inbox.h +++ b/CleverTapSDK/CleverTap+Inbox.h @@ -242,5 +242,12 @@ typedef void (^CleverTapInboxUpdatedBlock)(void); */ - (void)recordInboxNotificationClickedEventForID:(NSString * _Nonnull)messageId; +/*! + @method + + @abstract + This method dismisses the inbox controller + */ +- (void)dismissAppInbox; @end diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index 370bb1b6..e962c7ed 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -4372,6 +4372,16 @@ - (CleverTapInboxViewController * _Nullable)newInboxViewControllerWithConfig:(Cl return [[CleverTapInboxViewController alloc] initWithMessages:messages config:config delegate:delegate analyticsDelegate:self]; } +- (void)dismissAppInbox{ + UIApplication *application = [[self class] getSharedApplication]; + UIWindow *window = [[application delegate] window]; + if ([window rootViewController] != nil){ + UINavigationController *nv = (UINavigationController *)[[window rootViewController] presentedViewController]; + if ([nv.topViewController isKindOfClass:[CleverTapInboxViewController class]]){ + [[window rootViewController] dismissViewControllerAnimated:YES completion:nil]; + } + } +} #pragma mark Private From 6cb577e06b3b1961d50bfeb15ec584c380417c5c Mon Sep 17 00:00:00 2001 From: Aishwarya Nanna Date: Mon, 20 Mar 2023 17:22:12 +0530 Subject: [PATCH 09/20] - Added nil and empty check for messageIds array --- CleverTapSDK/CleverTap.m | 6 +++++- CleverTapSDK/Inbox/controllers/CTInboxController.m | 12 +++++++++--- SwiftStarter/SwiftStarter/ViewController.swift | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index 0a485872..d8004202 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -4377,7 +4377,11 @@ - (void)markReadInboxMessagesForIDs:(NSArray *_Nonnull)messageIds{ if (![self _isInboxInitialized]) { return; } - [self.inboxController markReadMessagesWithId:messageIds]; + if (messageIds != nil && [messageIds count] == 0){ + [self.inboxController markReadMessagesWithId:messageIds]; + }else{ + CleverTapLogStaticDebug(@"App Inbox message ids array is null or empty"); + } } - (void)registerInboxUpdatedBlock:(CleverTapInboxUpdatedBlock)block { diff --git a/CleverTapSDK/Inbox/controllers/CTInboxController.m b/CleverTapSDK/Inbox/controllers/CTInboxController.m index 75562435..7549dc09 100755 --- a/CleverTapSDK/Inbox/controllers/CTInboxController.m +++ b/CleverTapSDK/Inbox/controllers/CTInboxController.m @@ -125,9 +125,15 @@ - (void)markReadMessageWithId:(NSString *)messageId { - (void)markReadMessagesWithId:(NSArray *_Nonnull)messageIds { [privateContext performBlock:^{ for (NSString *ids in messageIds) { - CTMessageMO *message = [self _messageForId:ids]; - if (message) { - [message setValue:@YES forKey:@"isRead"]; + if (ids != nil && ![ids isEqualToString:@""]){ + CTMessageMO *message = [self _messageForId:ids]; + if (message) { + [message setValue:@YES forKey:@"isRead"]; + }else{ + CleverTapLogStaticDebug(@"%@ is invalid App-inbox ID", ids); + } + }else{ + CleverTapLogStaticDebug(@"App Inbox ID is null or not a string"); } } [self _save]; diff --git a/SwiftStarter/SwiftStarter/ViewController.swift b/SwiftStarter/SwiftStarter/ViewController.swift index 071ab422..dc5005ce 100644 --- a/SwiftStarter/SwiftStarter/ViewController.swift +++ b/SwiftStarter/SwiftStarter/ViewController.swift @@ -254,6 +254,8 @@ extension ViewController: UITableViewDataSource, UITableViewDelegate{ let navigationController = UINavigationController.init(rootViewController: inboxController) self.present(navigationController, animated: true, completion: nil) } + var array: [String]? = nil + CleverTap.sharedInstance()?.markReadInboxMessages(forIDs: array!) } func navigateToWebview() { From e792bf077714d9d4041f7dee3cb1d8d0c379cd92 Mon Sep 17 00:00:00 2001 From: Aishwarya Nanna Date: Mon, 20 Mar 2023 17:23:39 +0530 Subject: [PATCH 10/20] removing test code --- SwiftStarter/SwiftStarter/ViewController.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/SwiftStarter/SwiftStarter/ViewController.swift b/SwiftStarter/SwiftStarter/ViewController.swift index dc5005ce..071ab422 100644 --- a/SwiftStarter/SwiftStarter/ViewController.swift +++ b/SwiftStarter/SwiftStarter/ViewController.swift @@ -254,8 +254,6 @@ extension ViewController: UITableViewDataSource, UITableViewDelegate{ let navigationController = UINavigationController.init(rootViewController: inboxController) self.present(navigationController, animated: true, completion: nil) } - var array: [String]? = nil - CleverTap.sharedInstance()?.markReadInboxMessages(forIDs: array!) } func navigateToWebview() { From fb7193aa53bb1083ed143afc79257c7baa9b4eb7 Mon Sep 17 00:00:00 2001 From: Aishwarya Nanna Date: Mon, 20 Mar 2023 18:10:56 +0530 Subject: [PATCH 11/20] -changed enableLocation from class method to instance method --- CleverTapSDK/CTLocationManager.h | 2 -- CleverTapSDK/CTLocationManager.m | 4 ---- CleverTapSDK/CleverTap.h | 2 +- CleverTapSDK/CleverTap.m | 4 ++-- 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/CleverTapSDK/CTLocationManager.h b/CleverTapSDK/CTLocationManager.h index b95c71d9..3ac160a5 100644 --- a/CleverTapSDK/CTLocationManager.h +++ b/CleverTapSDK/CTLocationManager.h @@ -3,8 +3,6 @@ @interface CTLocationManager : NSObject -//#if defined(CLEVERTAP_LOCATION) + (void)getLocationWithSuccess:(void (^)(CLLocationCoordinate2D location))success andError:(void (^)(NSString *reason))error; -//#endif @end diff --git a/CleverTapSDK/CTLocationManager.m b/CleverTapSDK/CTLocationManager.m index b50c81e2..ef0fcb3e 100644 --- a/CleverTapSDK/CTLocationManager.m +++ b/CleverTapSDK/CTLocationManager.m @@ -13,7 +13,6 @@ @interface CleverTapLocationRequest : NSObject @implementation CleverTapLocationRequest @end -//#if defined(CLEVERTAP_LOCATION) NSString *const kLocationTimeoutError = @"Location Request Timed Out: Have You Set NSLocationWhenInUseUsageDescription in Your Info.plist?"; NSString *const kLocationServicesNotEnabled = @"Location Services Not Enabled"; NSString *const kLocationPermissionDenied = @"Location Permission Denied"; @@ -26,11 +25,9 @@ @implementation CleverTapLocationRequest static NSMutableArray *pendingRequests; static NSObject *requestsLockObject; -//#endif @implementation CTLocationManager -//#if defined(CLEVERTAP_LOCATION) /** NOTE: If NSLocationWhenInUseUsageDescription is not set in the app's Info.plist, calls to the CLLocationManager instance will fail silently. Rely on the location timeout to stop updating and return an error in this case. */ @@ -201,6 +198,5 @@ + (void)stopUpdatingLocation { locationManager.delegate = nil; [self cancelLocationTimeout]; } -//#endif @end diff --git a/CleverTapSDK/CleverTap.h b/CleverTapSDK/CleverTap.h index 1f884a8d..c01b8722 100644 --- a/CleverTapSDK/CleverTap.h +++ b/CleverTapSDK/CleverTap.h @@ -364,7 +364,7 @@ extern NSString * _Nonnull const CleverTapGeofencesDidUpdateNotification; Call this method (typically once at app launch) to enable the location API. */ -+ (void)enableLocation:(BOOL)enabled; +- (void)enableLocation:(BOOL)enabled; /*! @method diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index 9438a43e..e4c981bb 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -4080,8 +4080,8 @@ - (BOOL)geofenceLocation { return _geofenceLocation; } -+ (void)enableLocation:(BOOL)enabled{ - [[self sharedInstance] setLocationEnabled:enabled]; +- (void)enableLocation:(BOOL)enabled{ + [self setLocationEnabled:enabled]; } - (void)setLocationEnabled:(BOOL)enabled { From 4b78648a850e9b6cabc7d1fad1b30df3fecc72e2 Mon Sep 17 00:00:00 2001 From: Akash Malhotra Date: Mon, 20 Mar 2023 20:37:53 +0530 Subject: [PATCH 12/20] minor fixes and log message changes --- CleverTapSDK/CleverTap.m | 7 ++++--- CleverTapSDK/Inbox/controllers/CTInboxController.m | 10 ++++++---- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index d8004202..873473b5 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -4377,10 +4377,11 @@ - (void)markReadInboxMessagesForIDs:(NSArray *_Nonnull)messageIds{ if (![self _isInboxInitialized]) { return; } - if (messageIds != nil && [messageIds count] == 0){ + if (messageIds != nil && [messageIds count] > 0) { [self.inboxController markReadMessagesWithId:messageIds]; - }else{ - CleverTapLogStaticDebug(@"App Inbox message ids array is null or empty"); + } + else { + CleverTapLogStaticDebug(@"App Inbox Message IDs array is null or empty"); } } diff --git a/CleverTapSDK/Inbox/controllers/CTInboxController.m b/CleverTapSDK/Inbox/controllers/CTInboxController.m index 7549dc09..36519d9e 100755 --- a/CleverTapSDK/Inbox/controllers/CTInboxController.m +++ b/CleverTapSDK/Inbox/controllers/CTInboxController.m @@ -129,11 +129,13 @@ - (void)markReadMessagesWithId:(NSArray *_Nonnull)messageIds { CTMessageMO *message = [self _messageForId:ids]; if (message) { [message setValue:@YES forKey:@"isRead"]; - }else{ - CleverTapLogStaticDebug(@"%@ is invalid App-inbox ID", ids); } - }else{ - CleverTapLogStaticDebug(@"App Inbox ID is null or not a string"); + else { + CleverTapLogStaticDebug(@"Cannot mark App Inbox Message as read because Message ID %@ is invalid.", ids); + } + } + else { + CleverTapLogStaticDebug(@"Cannot mark App Inbox Message as read because Message ID is null or not a string."); } } [self _save]; From 5d9b694c89ae4b54c394b5428da740068795630d Mon Sep 17 00:00:00 2001 From: Akash Malhotra Date: Mon, 20 Mar 2023 21:27:38 +0530 Subject: [PATCH 13/20] refactored locationEnabled to be static and project based --- CleverTapSDK/CleverTap.h | 2 +- CleverTapSDK/CleverTap.m | 25 +++++++++---------------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/CleverTapSDK/CleverTap.h b/CleverTapSDK/CleverTap.h index c01b8722..1f884a8d 100644 --- a/CleverTapSDK/CleverTap.h +++ b/CleverTapSDK/CleverTap.h @@ -364,7 +364,7 @@ extern NSString * _Nonnull const CleverTapGeofencesDidUpdateNotification; Call this method (typically once at app launch) to enable the location API. */ -- (void)enableLocation:(BOOL)enabled; ++ (void)enableLocation:(BOOL)enabled; /*! @method diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index e4c981bb..1296fcfa 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -77,6 +77,7 @@ static const void *const kQueueKey = &kQueueKey; static const void *const kNotificationQueueKey = &kNotificationQueueKey; +static BOOL isLocationEnabled; static NSRecursiveLock *instanceLock; static const int kMaxBatchSize = 49; @@ -250,8 +251,6 @@ @interface CleverTap () { @property (atomic, assign) BOOL geofenceLocation; @property (nonatomic, strong) NSString *gfSDKVersion; -@property (atomic, assign) BOOL isLocationEnabled; - - (instancetype)init __unavailable; @end @@ -4080,27 +4079,21 @@ - (BOOL)geofenceLocation { return _geofenceLocation; } -- (void)enableLocation:(BOOL)enabled{ - [self setLocationEnabled:enabled]; -} - -- (void)setLocationEnabled:(BOOL)enabled { - _isLocationEnabled = enabled; -} - -- (BOOL)getIsLocationEnabled { - return _isLocationEnabled; ++ (void)enableLocation:(BOOL)enabled{ + isLocationEnabled = enabled; } + (void)getLocationWithSuccess:(void (^)(CLLocationCoordinate2D location))success andError:(void (^)(NSString *reason))error; { #if defined(CLEVERTAP_LOCATION) [CTLocationManager getLocationWithSuccess:success andError:error]; #else - if ([[self sharedInstance] getIsLocationEnabled]){ + if (isLocationEnabled){ [CTLocationManager getLocationWithSuccess:success andError:error]; - - }else{ - CleverTapLogStaticInfo(@"To Enable CleverTap Location services/apis please build the SDK with the CLEVERTAP_LOCATION macro or use enableLocation method"); + } + else { + NSString *errorMsg = @"To Enable CleverTap Location services/apis please build the SDK with the CLEVERTAP_LOCATION macro or use enableLocation method"; + CleverTapLogStaticDebug(@"%@",errorMsg); + error(errorMsg); } #endif } From 63f23aa168f43135aedcee311f21963221842a30 Mon Sep 17 00:00:00 2001 From: Akash Malhotra Date: Mon, 20 Mar 2023 21:34:59 +0530 Subject: [PATCH 14/20] minor indentation changes --- CleverTapSDK/CleverTap.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index e962c7ed..a0ffca0b 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -4372,12 +4372,12 @@ - (CleverTapInboxViewController * _Nullable)newInboxViewControllerWithConfig:(Cl return [[CleverTapInboxViewController alloc] initWithMessages:messages config:config delegate:delegate analyticsDelegate:self]; } -- (void)dismissAppInbox{ +- (void)dismissAppInbox { UIApplication *application = [[self class] getSharedApplication]; UIWindow *window = [[application delegate] window]; - if ([window rootViewController] != nil){ - UINavigationController *nv = (UINavigationController *)[[window rootViewController] presentedViewController]; - if ([nv.topViewController isKindOfClass:[CleverTapInboxViewController class]]){ + if ([window rootViewController] != nil) { + UINavigationController *navigationController = (UINavigationController *)[[window rootViewController] presentedViewController]; + if ([navigationController.topViewController isKindOfClass:[CleverTapInboxViewController class]]) { [[window rootViewController] dismissViewControllerAnimated:YES completion:nil]; } } From 617849a6620ca2d43f6f4b62f305c55abdb05e2b Mon Sep 17 00:00:00 2001 From: Akash Malhotra Date: Tue, 21 Mar 2023 11:05:33 +0530 Subject: [PATCH 15/20] Made dismissInbox run on main thread --- CleverTapSDK/CleverTap.m | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index a0ffca0b..2371ab66 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -4373,14 +4373,16 @@ - (CleverTapInboxViewController * _Nullable)newInboxViewControllerWithConfig:(Cl } - (void)dismissAppInbox { - UIApplication *application = [[self class] getSharedApplication]; - UIWindow *window = [[application delegate] window]; - if ([window rootViewController] != nil) { - UINavigationController *navigationController = (UINavigationController *)[[window rootViewController] presentedViewController]; - if ([navigationController.topViewController isKindOfClass:[CleverTapInboxViewController class]]) { - [[window rootViewController] dismissViewControllerAnimated:YES completion:nil]; + [[self class] runSyncMainQueue:^{ + UIApplication *application = [[self class] getSharedApplication]; + UIWindow *window = [[application delegate] window]; + if ([window rootViewController] != nil) { + UINavigationController *navigationController = (UINavigationController *)[[window rootViewController] presentedViewController]; + if ([navigationController.topViewController isKindOfClass:[CleverTapInboxViewController class]]) { + [[window rootViewController] dismissViewControllerAnimated:YES completion:nil]; + } } - } + }]; } #pragma mark Private From 63cc10e3085511b400161def709e05b5d4bd6f64 Mon Sep 17 00:00:00 2001 From: Akash Malhotra Date: Tue, 21 Mar 2023 11:14:30 +0530 Subject: [PATCH 16/20] minor log message changes --- CleverTapSDK/Inbox/controllers/CTInboxController.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CleverTapSDK/Inbox/controllers/CTInboxController.m b/CleverTapSDK/Inbox/controllers/CTInboxController.m index 2d684d89..e8d5c229 100755 --- a/CleverTapSDK/Inbox/controllers/CTInboxController.m +++ b/CleverTapSDK/Inbox/controllers/CTInboxController.m @@ -109,11 +109,11 @@ - (void)deleteMessagesWithId:(NSArray *_Nonnull)messageIds { [toDeleteInboxMessages addObject:msg]; } else { - NSLog(@"%@ is invalid App-inbox ID", ids); + CleverTapLogStaticDebug(@"Cannot delete App Inbox Message because Message ID %@ is invalid.", ids) } } else { - NSLog(@"App Inbox ID is null or not a string"); + CleverTapLogStaticDebug(@"Cannot delete App Inbox Message because Message ID is null or not a string."); } } if ([toDeleteInboxMessages count] > 0) { From 72388c984c5252689c1256578898d4645763e550 Mon Sep 17 00:00:00 2001 From: Akash Malhotra Date: Tue, 21 Mar 2023 13:04:11 +0530 Subject: [PATCH 17/20] Update CHANGELOG.md --- CHANGELOG.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 805dba2e..0f3587b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,14 @@ # Change Log All notable changes to this project will be documented in this file. -### [Version 4.2.1](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/4.2.1) (February 03, 2023) +### [Version 4.2.1](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/4.2.1) (March 21, 2023) #### Added -- Adds a new `enableLocation` API for enabling location in case of SPM. -- Adds a public instance method `markReadInboxMessagesForIDs` for marking multiple App Inbox messages as read by passing a collection of `messageID`s. +- Adds a public method `dismissAppInbox` to dismiss App Inbox. +- Adds a public method `enableLocation` for enabling location API in case of SPM. +- Adds a public method `markReadInboxMessagesForIDs` for marking multiple App Inbox messages as read by passing a collection of `messageID`s. +- Fixes a bug where CoreData would crash with threading inconsistency exceptions. +- Fixes a bug where the method `deleteInboxMessageForID` would cause a crash when the message ID was null or invalid. ### [Version 4.2.0](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/4.2.0) (December 13, 2022) From 76b103ef23909c114d34d9649b4623a3e5c53c78 Mon Sep 17 00:00:00 2001 From: Akash Malhotra Date: Tue, 21 Mar 2023 16:39:42 +0530 Subject: [PATCH 18/20] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f3587b6..7c14ce17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file. - Adds a public method `enableLocation` for enabling location API in case of SPM. - Adds a public method `markReadInboxMessagesForIDs` for marking multiple App Inbox messages as read by passing a collection of `messageID`s. - Fixes a bug where CoreData would crash with threading inconsistency exceptions. -- Fixes a bug where the method `deleteInboxMessageForID` would cause a crash when the message ID was null or invalid. +- Fixes a bug where the method `deleteInboxMessagesForIDs` would cause a crash when the message ID was null or invalid. ### [Version 4.2.0](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/4.2.0) (December 13, 2022) From 213087cf018ddcf6175be012d7fc5e7da153c0b5 Mon Sep 17 00:00:00 2001 From: Aishwarya Nanna Date: Wed, 22 Mar 2023 12:56:40 +0530 Subject: [PATCH 19/20] added minor check in dismissAppInbox method --- CleverTapSDK/CleverTap.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CleverTapSDK/CleverTap.m b/CleverTapSDK/CleverTap.m index e489eda9..68d1651d 100644 --- a/CleverTapSDK/CleverTap.m +++ b/CleverTapSDK/CleverTap.m @@ -4400,7 +4400,8 @@ - (void)dismissAppInbox { [[self class] runSyncMainQueue:^{ UIApplication *application = [[self class] getSharedApplication]; UIWindow *window = [[application delegate] window]; - if ([window rootViewController] != nil) { + UIViewController *presentedViewcontoller = [[window rootViewController] presentedViewController]; + if ([presentedViewcontoller isKindOfClass:[UINavigationController class]]) { UINavigationController *navigationController = (UINavigationController *)[[window rootViewController] presentedViewController]; if ([navigationController.topViewController isKindOfClass:[CleverTapInboxViewController class]]) { [[window rootViewController] dismissViewControllerAnimated:YES completion:nil]; From 25deb7466f0995f26a7b39d09f32b8ef29a1e1d8 Mon Sep 17 00:00:00 2001 From: Aishwarya Nanna Date: Wed, 22 Mar 2023 14:03:59 +0530 Subject: [PATCH 20/20] updated release date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c14ce17..2aa2470d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Change Log All notable changes to this project will be documented in this file. -### [Version 4.2.1](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/4.2.1) (March 21, 2023) +### [Version 4.2.1](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/4.2.1) (March 22, 2023) #### Added - Adds a public method `dismissAppInbox` to dismiss App Inbox.