diff --git a/.versions b/.versions
index 70f790c..1bc9bee 100644
--- a/.versions
+++ b/.versions
@@ -1,2 +1,2 @@
-countly:countly-sdk-js@20.11.0
+countly:countly-sdk-js@20.11.1
meteor@1.9.2
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac94d90..fd05469 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 20.11.1
+* "setLoggingEnabled" call issues fixed.
+* Updated underlying android SDK to 20.11.8
+* Underlying iOS SDK version is 20.11.1
+
## 20.11.0
* !! Due to cocoapods issue with Xcode 12, we have added the iOS SDK as source code instead of Pod. Due to that change you may need to remove the ios platform and add it again.
* !! Consent change !! To use remote config, you now need to give "remote-config" consent
diff --git a/Countly.js b/Countly.js
index 7fc0a85..e5bcd2e 100644
--- a/Countly.js
+++ b/Countly.js
@@ -2,8 +2,9 @@ Countly = {};
Countly.serverUrl = "";
Countly.appKey = "";
Countly.ready = false;
-Countly.version = "20.11.0";
+Countly.version = "20.11.1";
Countly.isDebug = false;
+Countly.isInitCalled = false;
if (window.cordova.platformId == "android") {
Countly.isAndroid = true;
Countly.messagingMode = {"TEST": "2", "PRODUCTION": "0"};
@@ -24,6 +25,8 @@ Countly.init = function(serverUrl,appKey, deviceId){
args.push(deviceId || "");
};
+ Countly.isInitCalled = true;
+
return new Promise((resolve,reject) => {
cordova.exec(resolve,reject,"CountlyCordova","init",args);
});
@@ -59,9 +62,16 @@ Countly.recordView = function(recordView, segments){
* Set to true if you want to enable countly internal debugging logs
* Should be call before Countly init
*/
-Countly.setLoggingEnabled = function(isDebug){
+Countly.setLoggingEnabled = function(isDebug = true){
+ isDebug = isDebug.toString() == "true" ? true : false;
+ if(this.isInitCalled) {
+ if(Countly.isDebug){
+ console.warn("setLoggingEnabled, should be call before init");
+ }
+ return;
+ }
Countly.isDebug = isDebug;
- var args = [isDebug?"true": "false"];
+ var args = [isDebug.toString()];
cordova.exec(Countly.onSuccess,Countly.onError,"CountlyCordova","setLoggingEnabled",args);
}
diff --git a/README.md b/README.md
index f50a3a1..efbd988 100644
--- a/README.md
+++ b/README.md
@@ -21,10 +21,10 @@ For more information about how to use this SDK inside your mobile app, [click th
Security is very important to us. If you discover any issue regarding security, please disclose the information responsibly by sending an email to security@count.ly and **not by creating a GitHub issue**.
-## Acknowledgements
+## Acknowledgements
This SDK was initially written by Panteon Technologies (ufuk@panteon.com.tr).
-It's now maintained by Trinisoft Technologies (trinisofttechnologies@gmail.com).
+From 2014 to 2020 it was maintained by Trinisoft Technologies developers (trinisofttechnologies@gmail.com).
## Badges
diff --git a/package.js b/package.js
index 088e0f9..38225ff 100644
--- a/package.js
+++ b/package.js
@@ -1,6 +1,6 @@
Package.describe({
name: 'countly:countly-sdk-js',
- version: '20.11.0',
+ version: '20.11.1',
summary: 'Countly is an innovative, real-time, open source mobile analytics and push notifications platform. It collects data from mobile devices, and visualizes this information to analyze mobile application usage and end-user behavior. There are two parts of Countly: the server that collects and analyzes data, and mobile SDK that sends this data. Both parts are open source with different licensing terms.',
git: 'https://github.com/Countly/countly-sdk-cordova.git',
documentation: 'README.md'
diff --git a/package.json b/package.json
index 0aea83e..77ff050 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "countly-sdk-js",
- "version": "20.11.0",
+ "version": "20.11.1",
"description": "Countly is an innovative, real-time, open source mobile analytics and push notifications platform. It collects data from mobile devices, and visualizes this information to analyze mobile application usage and end-user behavior. There are two parts of Countly: the server that collects and analyzes data, and mobile SDK that sends this data. Both parts are open source with different licensing terms.",
"cordova": {
"id": "countly-sdk-js",
diff --git a/plugin.xml b/plugin.xml
index f284d7b..abf735c 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -1,15 +1,15 @@
-
+
- Countly
+ Countly Cordova SDK
Countly is an innovative, real-time, open source mobile analytics and push notifications platform. It collects data from mobile devices, and visualizes this information to analyze mobile application usage and end-user behavior. There are two parts of Countly: the server that collects and analyzes data, and mobile SDK that sends this data. Both parts are open source with different licensing terms.
- Trinisoft Technologies Pvt. Ltd.
+ Countly
- Open source with different licensing terms.
+ MIT
Event, Mobile analytical
@@ -141,7 +141,7 @@
-
+
diff --git a/src/android/CountlyNative.java b/src/android/CountlyNative.java
index d47b2c2..9dc199e 100644
--- a/src/android/CountlyNative.java
+++ b/src/android/CountlyNative.java
@@ -36,7 +36,7 @@
public class CountlyNative {
public static final String TAG = "CountlyCordovaPlugin";
- private String COUNTLY_CORDOVA_SDK_VERSION_STRING = "20.11.0";
+ private String COUNTLY_CORDOVA_SDK_VERSION_STRING = "20.11.1";
private String COUNTLY_CORDOVA_SDK_NAME = "js-cordovab-android";
private Countly.CountlyMessagingMode pushTokenTypeVariable = Countly.CountlyMessagingMode.PRODUCTION;
diff --git a/src/ios/CountlyNative.m b/src/ios/CountlyNative.m
index 2a474fa..d31d06c 100644
--- a/src/ios/CountlyNative.m
+++ b/src/ios/CountlyNative.m
@@ -19,7 +19,7 @@
Boolean isInitialized = false;
NSString *const pushPluginApplicationDidBecomeActiveNotification = @"pushPluginApplicationDidBecomeActiveNotification";
-NSString* const kCountlyCordovaSDKVersion = @"20.11.0";
+NSString* const kCountlyCordovaSDKVersion = @"20.11.1";
NSString* const kCountlyCordovaSDKName = @"js-cordovab-ios";
@interface CountlyFeedbackWidget ()
diff --git a/src/ios/CountlyiOS/Countly.h b/src/ios/CountlyiOS/Countly.h
index b25476f..08541c8 100644
--- a/src/ios/CountlyiOS/Countly.h
+++ b/src/ios/CountlyiOS/Countly.h
@@ -446,6 +446,13 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)recordCrashLog:(NSString *)log;
+/**
+ * Clears all custom crash logs.
+ * @discussion Custom crash logs recorded using @c recordCrashLog: method so far will be cleared.
+ */
+- (void)clearCrashLogs;
+
+
/**
* @c crashLog: method is deprecated. Please use @c recordCrashLog: method instead.
* @discussion Be advised, parameter type changed to plain @c NSString from string format, for better Swift compatibility.
@@ -478,7 +485,7 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (void)recordView:(NSString *)viewName segmentation:(NSDictionary *)segmentation;
-#if (TARGET_OS_IOS)
+#if (TARGET_OS_IOS || TARGET_OS_TV)
/**
* Adds exception for AutoViewTracking.
* @discussion @c UIViewControllers with specified title or class name will be ignored by AutoViewTracking and their appearances and disappearances will not be recorded.
diff --git a/src/ios/CountlyiOS/Countly.m b/src/ios/CountlyiOS/Countly.m
index e781f2a..eaa6a75 100644
--- a/src/ios/CountlyiOS/Countly.m
+++ b/src/ios/CountlyiOS/Countly.m
@@ -72,6 +72,8 @@ - (void)startWithConfig:(CountlyConfig *)config
CountlyCommon.sharedInstance.hasStarted = YES;
CountlyCommon.sharedInstance.enableDebug = config.enableDebug;
CountlyCommon.sharedInstance.loggerDelegate = config.loggerDelegate;
+ CountlyCommon.sharedInstance.internalLogLevel = config.internalLogLevel;
+
CountlyConsentManager.sharedInstance.requiresConsent = config.requiresConsent;
if (!config.appKey.length || [config.appKey isEqualToString:@"YOUR_APP_KEY"])
@@ -80,7 +82,7 @@ - (void)startWithConfig:(CountlyConfig *)config
if (!config.host.length || [config.host isEqualToString:@"https://YOUR_COUNTLY_SERVER"])
[NSException raise:@"CountlyHostNotSetException" format:@"host property on CountlyConfig object is not set"];
- COUNTLY_LOG(@"Initializing with %@ SDK v%@", CountlyCommon.sharedInstance.SDKName, CountlyCommon.sharedInstance.SDKVersion);
+ CLY_LOG_I(@"Initializing with %@ SDK v%@", CountlyCommon.sharedInstance.SDKName, CountlyCommon.sharedInstance.SDKVersion);
if (!CountlyDeviceInfo.sharedInstance.deviceID || config.resetStoredDeviceID)
{
@@ -186,6 +188,8 @@ - (void)startWithConfig:(CountlyConfig *)config
- (void)setNewAppKey:(NSString *)newAppKey
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, newAppKey);
+
if (!newAppKey.length)
return;
@@ -200,23 +204,31 @@ - (void)setNewAppKey:(NSString *)newAppKey
- (void)setCustomHeaderFieldValue:(NSString *)customHeaderFieldValue
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, customHeaderFieldValue);
+
CountlyConnectionManager.sharedInstance.customHeaderFieldValue = customHeaderFieldValue.copy;
[CountlyConnectionManager.sharedInstance proceedOnQueue];
}
- (void)flushQueues
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[CountlyPersistency.sharedInstance flushEvents];
[CountlyPersistency.sharedInstance flushQueue];
}
- (void)replaceAllAppKeysInQueueWithCurrentAppKey
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[CountlyPersistency.sharedInstance replaceAllAppKeysInQueueWithCurrentAppKey];
}
- (void)removeDifferentAppKeysFromQueue
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[CountlyPersistency.sharedInstance removeDifferentAppKeysFromQueue];
}
@@ -224,18 +236,24 @@ - (void)removeDifferentAppKeysFromQueue
- (void)beginSession
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
if (CountlyCommon.sharedInstance.manualSessionHandling)
[CountlyConnectionManager.sharedInstance beginSession];
}
- (void)updateSession
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
if (CountlyCommon.sharedInstance.manualSessionHandling)
[CountlyConnectionManager.sharedInstance updateSession];
}
- (void)endSession
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
if (CountlyCommon.sharedInstance.manualSessionHandling)
[CountlyConnectionManager.sharedInstance endSession];
}
@@ -255,13 +273,17 @@ - (void)onTimer:(NSTimer *)timer
- (void)suspend
{
+#if (TARGET_OS_WATCH)
+ CLY_LOG_I(@"%s", __FUNCTION__);
+#endif
+
if (!CountlyCommon.sharedInstance.hasStarted)
return;
if (isSuspended)
return;
- COUNTLY_LOG(@"Suspending...");
+ CLY_LOG_D(@"Suspending...");
isSuspended = YES;
@@ -277,6 +299,10 @@ - (void)suspend
- (void)resume
{
+#if (TARGET_OS_WATCH)
+ CLY_LOG_I(@"%s", __FUNCTION__);
+#endif
+
if (!CountlyCommon.sharedInstance.hasStarted)
return;
@@ -303,19 +329,19 @@ - (void)resume
- (void)applicationDidEnterBackground:(NSNotification *)notification
{
- COUNTLY_LOG(@"App did enter background.");
+ CLY_LOG_D(@"App did enter background.");
[self suspend];
}
- (void)applicationWillEnterForeground:(NSNotification *)notification
{
- COUNTLY_LOG(@"App will enter foreground.");
+ CLY_LOG_D(@"App will enter foreground.");
[self resume];
}
- (void)applicationWillTerminate:(NSNotification *)notification
{
- COUNTLY_LOG(@"App will terminate.");
+ CLY_LOG_D(@"App will terminate.");
CountlyConnectionManager.sharedInstance.isTerminating = YES;
@@ -345,11 +371,15 @@ - (void)dealloc
- (NSString *)deviceID
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
return CountlyDeviceInfo.sharedInstance.deviceID.cly_URLEscaped;
}
- (CLYDeviceIDType)deviceIDType
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
if (CountlyDeviceInfo.sharedInstance.isDeviceIDTemporary)
return CLYDeviceIDTypeTemporary;
@@ -365,6 +395,8 @@ - (CLYDeviceIDType)deviceIDType
- (void)setNewDeviceID:(NSString *)deviceID onServer:(BOOL)onServer
{
+ CLY_LOG_I(@"%s %@ %d", __FUNCTION__, deviceID, onServer);
+
if (!CountlyCommon.sharedInstance.hasStarted)
return;
@@ -377,13 +409,13 @@ - (void)setNewDeviceID:(NSString *)deviceID onServer:(BOOL)onServer
if ([deviceID isEqualToString:CountlyDeviceInfo.sharedInstance.deviceID])
{
- COUNTLY_LOG(@"Attempted to set the same device ID again. So, setting new device ID is aborted.");
+ CLY_LOG_W(@"Attempted to set the same device ID again. So, setting new device ID is aborted.");
return;
}
if (CountlyDeviceInfo.sharedInstance.isDeviceIDTemporary)
{
- COUNTLY_LOG(@"Going out of CLYTemporaryDeviceID mode and switching back to normal mode.");
+ CLY_LOG_I(@"Going out of CLYTemporaryDeviceID mode and switching back to normal mode.");
[CountlyDeviceInfo.sharedInstance initializeDeviceID:deviceID];
@@ -398,7 +430,7 @@ - (void)setNewDeviceID:(NSString *)deviceID onServer:(BOOL)onServer
if ([deviceID isEqualToString:CLYTemporaryDeviceID] && onServer)
{
- COUNTLY_LOG(@"Attempted to set device ID as CLYTemporaryDeviceID with onServer option. So, onServer value is overridden as NO.");
+ CLY_LOG_W(@"Attempted to set device ID as CLYTemporaryDeviceID with onServer option. So, onServer value is overridden as NO.");
onServer = NO;
}
@@ -434,6 +466,8 @@ - (void)storeCustomDeviceIDState:(NSString *)deviceID
#pragma mark - Consents
- (void)giveConsentForFeature:(NSString *)featureName
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, featureName);
+
if (!featureName.length)
return;
@@ -442,16 +476,22 @@ - (void)giveConsentForFeature:(NSString *)featureName
- (void)giveConsentForFeatures:(NSArray *)features
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, features);
+
[CountlyConsentManager.sharedInstance giveConsentForFeatures:features];
}
- (void)giveConsentForAllFeatures
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[CountlyConsentManager.sharedInstance giveConsentForAllFeatures];
}
- (void)cancelConsentForFeature:(NSString *)featureName
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, featureName);
+
if (!featureName.length)
return;
@@ -460,11 +500,15 @@ - (void)cancelConsentForFeature:(NSString *)featureName
- (void)cancelConsentForFeatures:(NSArray *)features
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, features);
+
[CountlyConsentManager.sharedInstance cancelConsentForFeatures:features];
}
- (void)cancelConsentForAllFeatures
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[CountlyConsentManager.sharedInstance cancelConsentForAllFeatures];
}
@@ -513,6 +557,8 @@ - (void)recordEvent:(NSString *)key segmentation:(NSDictionary *)segmentation co
- (void)recordEvent:(NSString *)key segmentation:(NSDictionary *)segmentation count:(NSUInteger)count sum:(double)sum duration:(NSTimeInterval)duration
{
+ CLY_LOG_I(@"%s %@ %@ %lu %f %f", __FUNCTION__, key, segmentation, (unsigned long)count, sum, duration);
+
if (!CountlyConsentManager.sharedInstance.consentForEvents)
return;
@@ -555,6 +601,8 @@ - (void)recordEvent:(NSString *)key segmentation:(NSDictionary *)segmentation co
- (void)startEvent:(NSString *)key
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, key);
+
if (!CountlyConsentManager.sharedInstance.consentForEvents)
return;
@@ -574,6 +622,8 @@ - (void)endEvent:(NSString *)key
- (void)endEvent:(NSString *)key segmentation:(NSDictionary *)segmentation count:(NSUInteger)count sum:(double)sum
{
+ CLY_LOG_I(@"%s %@ %@ %lu %f", __FUNCTION__, key, segmentation, (unsigned long)count, sum);
+
if (!CountlyConsentManager.sharedInstance.consentForEvents)
return;
@@ -581,7 +631,7 @@ - (void)endEvent:(NSString *)key segmentation:(NSDictionary *)segmentation count
if (!event)
{
- COUNTLY_LOG(@"Event with key '%@' not started yet or cancelled/ended before!", key);
+ CLY_LOG_W(@"Event with key '%@' not started yet or cancelled/ended before!", key);
return;
}
@@ -595,6 +645,8 @@ - (void)endEvent:(NSString *)key segmentation:(NSDictionary *)segmentation count
- (void)cancelEvent:(NSString *)key
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, key);
+
if (!CountlyConsentManager.sharedInstance.consentForEvents)
return;
@@ -602,11 +654,11 @@ - (void)cancelEvent:(NSString *)key
if (!event)
{
- COUNTLY_LOG(@"Event with key '%@' not started yet or cancelled/ended before!", key);
+ CLY_LOG_W(@"Event with key '%@' not started yet or cancelled/ended before!", key);
return;
}
- COUNTLY_LOG(@"Event with key '%@' cancelled!", key);
+ CLY_LOG_D(@"Event with key '%@' cancelled!", key);
}
@@ -616,26 +668,36 @@ - (void)cancelEvent:(NSString *)key
- (void)askForNotificationPermission
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[CountlyPushNotifications.sharedInstance askForNotificationPermissionWithOptions:0 completionHandler:nil];
}
- (void)askForNotificationPermissionWithOptions:(UNAuthorizationOptions)options completionHandler:(void (^)(BOOL granted, NSError * error))completionHandler;
{
+ CLY_LOG_I(@"%s %lu %@", __FUNCTION__, (unsigned long)options, completionHandler);
+
[CountlyPushNotifications.sharedInstance askForNotificationPermissionWithOptions:options completionHandler:completionHandler];
}
- (void)recordActionForNotification:(NSDictionary *)userInfo clickedButtonIndex:(NSInteger)buttonIndex;
{
+ CLY_LOG_I(@"%s %@ %ld", __FUNCTION__, userInfo, (long)buttonIndex);
+
[CountlyPushNotifications.sharedInstance recordActionForNotification:userInfo clickedButtonIndex:buttonIndex];
}
- (void)recordPushNotificationToken
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[CountlyPushNotifications.sharedInstance sendToken];
}
- (void)clearPushNotificationToken
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[CountlyPushNotifications.sharedInstance clearToken];
}
#endif
@@ -647,19 +709,21 @@ - (void)clearPushNotificationToken
- (void)recordLocation:(CLLocationCoordinate2D)location city:(NSString * _Nullable)city ISOCountryCode:(NSString * _Nullable)ISOCountryCode IP:(NSString * _Nullable)IP
{
+ CLY_LOG_I(@"%s %f,%f %@ %@ %@", __FUNCTION__, location.latitude, location.longitude, city, ISOCountryCode, IP);
+
[CountlyLocationManager.sharedInstance recordLocation:location city:city ISOCountryCode:ISOCountryCode IP:IP];
}
- (void)recordLocation:(CLLocationCoordinate2D)location
{
- COUNTLY_LOG(@"recordLocation: method is deprecated. Please use recordLocation:city:countryCode:IP: method instead.");
+ CLY_LOG_W(@"recordLocation: method is deprecated. Please use recordLocation:city:countryCode:IP: method instead.");
[CountlyLocationManager.sharedInstance recordLocation:location city:nil ISOCountryCode:nil IP:nil];
}
- (void)recordCity:(NSString *)city andISOCountryCode:(NSString *)ISOCountryCode
{
- COUNTLY_LOG(@"recordCity:andISOCountryCode: method is deprecated. Please use recordLocation:city:countryCode:IP: method instead.");
+ CLY_LOG_W(@"recordCity:andISOCountryCode: method is deprecated. Please use recordLocation:city:countryCode:IP: method instead.");
if (!city.length && !ISOCountryCode.length)
return;
@@ -669,7 +733,7 @@ - (void)recordCity:(NSString *)city andISOCountryCode:(NSString *)ISOCountryCode
- (void)recordIP:(NSString *)IP
{
- COUNTLY_LOG(@"recordIP: method is deprecated. Please use recordLocation:city:countryCode:IP: method instead.");
+ CLY_LOG_W(@"recordIP: method is deprecated. Please use recordLocation:city:countryCode:IP: method instead.");
if (!IP.length)
return;
@@ -679,6 +743,8 @@ - (void)recordIP:(NSString *)IP
- (void)disableLocationInfo
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[CountlyLocationManager.sharedInstance disableLocationInfo];
}
@@ -688,24 +754,37 @@ - (void)disableLocationInfo
- (void)recordHandledException:(NSException *)exception
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, exception);
+
[CountlyCrashReporter.sharedInstance recordException:exception withStackTrace:nil isFatal:NO];
}
- (void)recordHandledException:(NSException *)exception withStackTrace:(NSArray *)stackTrace
{
+ CLY_LOG_I(@"%s %@ %@", __FUNCTION__, exception, stackTrace);
+
[CountlyCrashReporter.sharedInstance recordException:exception withStackTrace:stackTrace isFatal:NO];
}
- (void)recordUnhandledException:(NSException *)exception withStackTrace:(NSArray * _Nullable)stackTrace
{
+ CLY_LOG_I(@"%s %@ %@", __FUNCTION__, exception, stackTrace);
+
[CountlyCrashReporter.sharedInstance recordException:exception withStackTrace:stackTrace isFatal:YES];
}
- (void)recordCrashLog:(NSString *)log
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, log);
+
[CountlyCrashReporter.sharedInstance log:log];
}
+- (void)clearCrashLogs
+{
+ [CountlyCrashReporter.sharedInstance clearCrashLogs];
+}
+
- (void)crashLog:(NSString *)format, ...
{
@@ -717,32 +796,44 @@ - (void)crashLog:(NSString *)format, ...
- (void)recordView:(NSString *)viewName;
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, viewName);
+
[CountlyViewTracking.sharedInstance startView:viewName customSegmentation:nil];
}
- (void)recordView:(NSString *)viewName segmentation:(NSDictionary *)segmentation
{
+ CLY_LOG_I(@"%s %@ %@", __FUNCTION__, viewName, segmentation);
+
[CountlyViewTracking.sharedInstance startView:viewName customSegmentation:segmentation];
}
-#if (TARGET_OS_IOS)
+#if (TARGET_OS_IOS || TARGET_OS_TV)
- (void)addExceptionForAutoViewTracking:(NSString *)exception
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, exception);
+
[CountlyViewTracking.sharedInstance addExceptionForAutoViewTracking:exception.copy];
}
- (void)removeExceptionForAutoViewTracking:(NSString *)exception
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, exception);
+
[CountlyViewTracking.sharedInstance removeExceptionForAutoViewTracking:exception.copy];
}
- (void)setIsAutoViewTrackingActive:(BOOL)isAutoViewTrackingActive
{
+ CLY_LOG_I(@"%s %d", __FUNCTION__, isAutoViewTrackingActive);
+
CountlyViewTracking.sharedInstance.isAutoViewTrackingActive = isAutoViewTrackingActive;
}
- (BOOL)isAutoViewTrackingActive
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
return CountlyViewTracking.sharedInstance.isAutoViewTrackingActive;
}
#endif
@@ -758,11 +849,15 @@ + (CountlyUserDetails *)user
- (void)userLoggedIn:(NSString *)userID
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, userID);
+
[self setNewDeviceID:userID onServer:YES];
}
- (void)userLoggedOut
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[self setNewDeviceID:CLYDefaultDeviceID onServer:NO];
}
@@ -773,16 +868,22 @@ - (void)userLoggedOut
- (void)askForStarRating:(void(^)(NSInteger rating))completion
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, completion);
+
[CountlyFeedbacks.sharedInstance showDialog:completion];
}
- (void)presentFeedbackWidgetWithID:(NSString *)widgetID completionHandler:(void (^)(NSError * error))completionHandler
{
+ CLY_LOG_I(@"%s %@ %@", __FUNCTION__, widgetID, completionHandler);
+
[CountlyFeedbacks.sharedInstance checkFeedbackWidgetWithID:widgetID completionHandler:completionHandler];
}
- (void)getFeedbackWidgets:(void (^)(NSArray *feedbackWidgets, NSError * error))completionHandler
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, completionHandler);
+
[CountlyFeedbacks.sharedInstance getFeedbackWidgets:completionHandler];
}
@@ -794,6 +895,8 @@ - (void)getFeedbackWidgets:(void (^)(NSArray *feedback
- (void)recordAttributionID:(NSString *)attributionID
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, attributionID);
+
if (!CountlyConsentManager.sharedInstance.consentForAttribution)
return;
@@ -808,21 +911,29 @@ - (void)recordAttributionID:(NSString *)attributionID
- (id)remoteConfigValueForKey:(NSString *)key
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, key);
+
return [CountlyRemoteConfig.sharedInstance remoteConfigValueForKey:key];
}
- (void)updateRemoteConfigWithCompletionHandler:(void (^)(NSError * error))completionHandler
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, completionHandler);
+
[CountlyRemoteConfig.sharedInstance updateRemoteConfigForKeys:nil omitKeys:nil completionHandler:completionHandler];
}
- (void)updateRemoteConfigOnlyForKeys:(NSArray *)keys completionHandler:(void (^)(NSError * error))completionHandler
{
+ CLY_LOG_I(@"%s %@ %@", __FUNCTION__, keys, completionHandler);
+
[CountlyRemoteConfig.sharedInstance updateRemoteConfigForKeys:keys omitKeys:nil completionHandler:completionHandler];
}
- (void)updateRemoteConfigExceptForKeys:(NSArray *)omitKeys completionHandler:(void (^)(NSError * error))completionHandler
{
+ CLY_LOG_I(@"%s %@ %@", __FUNCTION__, omitKeys, completionHandler);
+
[CountlyRemoteConfig.sharedInstance updateRemoteConfigForKeys:nil omitKeys:omitKeys completionHandler:completionHandler];
}
@@ -832,31 +943,43 @@ - (void)updateRemoteConfigExceptForKeys:(NSArray *)omitKeys completionHandler:(v
- (void)recordNetworkTrace:(NSString *)traceName requestPayloadSize:(NSInteger)requestPayloadSize responsePayloadSize:(NSInteger)responsePayloadSize responseStatusCode:(NSInteger)responseStatusCode startTime:(long long)startTime endTime:(long long)endTime
{
+ CLY_LOG_I(@"%s %@ %ld %ld %ld %lld %lld", __FUNCTION__, traceName, (long)requestPayloadSize, (long)responsePayloadSize, (long)responseStatusCode, startTime, endTime);
+
[CountlyPerformanceMonitoring.sharedInstance recordNetworkTrace:traceName requestPayloadSize:requestPayloadSize responsePayloadSize:responsePayloadSize responseStatusCode:responseStatusCode startTime:startTime endTime:endTime];
}
- (void)startCustomTrace:(NSString *)traceName
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, traceName);
+
[CountlyPerformanceMonitoring.sharedInstance startCustomTrace:traceName];
}
- (void)endCustomTrace:(NSString *)traceName metrics:(NSDictionary * _Nullable)metrics
{
+ CLY_LOG_I(@"%s %@ %@", __FUNCTION__, traceName, metrics);
+
[CountlyPerformanceMonitoring.sharedInstance endCustomTrace:traceName metrics:metrics];
}
- (void)cancelCustomTrace:(NSString *)traceName
{
+ CLY_LOG_I(@"%s %@", __FUNCTION__, traceName);
+
[CountlyPerformanceMonitoring.sharedInstance cancelCustomTrace:traceName];
}
- (void)clearAllCustomTraces
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
[CountlyPerformanceMonitoring.sharedInstance clearAllCustomTraces];
}
- (void)appLoadingFinished
{
+ CLY_LOG_I(@"%s", __FUNCTION__);
+
long long appLoadEndTime = floor(NSDate.date.timeIntervalSince1970 * 1000);
[CountlyPerformanceMonitoring.sharedInstance recordAppStartDurationTraceWithStartTime:appLoadStartTime endTime:appLoadEndTime];
diff --git a/src/ios/CountlyiOS/CountlyCommon.h b/src/ios/CountlyiOS/CountlyCommon.h
index 018826f..37e7e70 100644
--- a/src/ios/CountlyiOS/CountlyCommon.h
+++ b/src/ios/CountlyiOS/CountlyCommon.h
@@ -23,7 +23,11 @@
#import "CountlyRemoteConfig.h"
#import "CountlyPerformanceMonitoring.h"
-#define COUNTLY_LOG(fmt, ...) CountlyInternalLog(fmt, ##__VA_ARGS__)
+#define CLY_LOG_E(fmt, ...) CountlyInternalLog(CLYInternalLogLevelError, fmt, ##__VA_ARGS__)
+#define CLY_LOG_W(fmt, ...) CountlyInternalLog(CLYInternalLogLevelWarning, fmt, ##__VA_ARGS__)
+#define CLY_LOG_I(fmt, ...) CountlyInternalLog(CLYInternalLogLevelInfo, fmt, ##__VA_ARGS__)
+#define CLY_LOG_D(fmt, ...) CountlyInternalLog(CLYInternalLogLevelDebug, fmt, ##__VA_ARGS__)
+#define CLY_LOG_V(fmt, ...) CountlyInternalLog(CLYInternalLogLevelVerbose, fmt, ##__VA_ARGS__)
#if (TARGET_OS_IOS)
#import
@@ -59,11 +63,12 @@ NS_ERROR_ENUM(kCountlyErrorDomain)
@property (nonatomic) BOOL hasStarted;
@property (nonatomic) BOOL enableDebug;
@property (nonatomic, weak) id loggerDelegate;
+@property (nonatomic) CLYInternalLogLevel internalLogLevel;
@property (nonatomic) BOOL enableAppleWatch;
@property (nonatomic, copy) NSString* attributionID;
@property (nonatomic) BOOL manualSessionHandling;
-void CountlyInternalLog(NSString *format, ...) NS_FORMAT_FUNCTION(1,2);
+void CountlyInternalLog(CLYInternalLogLevel level, NSString *format, ...) NS_FORMAT_FUNCTION(2, 3);
void CountlyPrint(NSString *stringToPrint);
+ (instancetype)sharedInstance;
diff --git a/src/ios/CountlyiOS/CountlyCommon.m b/src/ios/CountlyiOS/CountlyCommon.m
index 44bc88c..5abcf49 100644
--- a/src/ios/CountlyiOS/CountlyCommon.m
+++ b/src/ios/CountlyiOS/CountlyCommon.m
@@ -33,7 +33,7 @@ @interface CountlyCommon ()
#endif
@end
-NSString* const kCountlySDKVersion = @"20.11.1";
+NSString* const kCountlySDKVersion = @"20.11.2";
NSString* const kCountlySDKName = @"objc-native-ios";
NSString* const kCountlyParentDeviceIDTransferKey = @"kCountlyParentDeviceIDTransferKey";
@@ -82,25 +82,40 @@ - (BOOL)hasStarted_
return _hasStarted;
}
-void CountlyInternalLog(NSString *format, ...)
+void CountlyInternalLog(CLYInternalLogLevel level, NSString *format, ...)
{
if (!CountlyCommon.sharedInstance.enableDebug && !CountlyCommon.sharedInstance.loggerDelegate)
return;
+ if (level > CountlyCommon.sharedInstance.internalLogLevel)
+ return;
+
va_list args;
va_start(args, format);
NSString* logString = [NSString.alloc initWithFormat:format arguments:args];
+ NSArray *logLevelPrefixes =
+ @[
+ @"None",
+ @"Error",
+ @"Warning",
+ @"Info",
+ @"Debug",
+ @"Verbose",
+ ];
+
+ logString = [NSString stringWithFormat:@"[%@] %@", logLevelPrefixes[level], logString];
+
#if DEBUG
if (CountlyCommon.sharedInstance.enableDebug)
CountlyPrint(logString);
#endif
- if (CountlyCommon.sharedInstance.loggerDelegate)
+ if ([CountlyCommon.sharedInstance.loggerDelegate respondsToSelector:@selector(internalLog:withLevel:)])
{
NSString* logStringWithPrefix = [NSString stringWithFormat:@"%@%@", kCountlyInternalLogPrefix, logString];
- [CountlyCommon.sharedInstance.loggerDelegate internalLog:logStringWithPrefix];
+ [CountlyCommon.sharedInstance.loggerDelegate internalLog:logStringWithPrefix withLevel:level];
}
va_end(args);
@@ -175,7 +190,7 @@ - (void)startAppleWatchMatching
if (WCSession.defaultSession.paired && WCSession.defaultSession.watchAppInstalled)
{
[WCSession.defaultSession transferUserInfo:@{kCountlyParentDeviceIDTransferKey: CountlyDeviceInfo.sharedInstance.deviceID}];
- COUNTLY_LOG(@"Transferring parent device ID %@ ...", CountlyDeviceInfo.sharedInstance.deviceID);
+ CLY_LOG_D(@"Transferring parent device ID %@ ...", CountlyDeviceInfo.sharedInstance.deviceID);
}
}
#endif
@@ -218,17 +233,17 @@ - (void)recordOrientation
if (!mode)
{
- COUNTLY_LOG(@"Interface orientation is not landscape or portrait.");
+ CLY_LOG_D(@"Interface orientation is not landscape or portrait.");
return;
}
if ([mode isEqualToString:self.lastInterfaceOrientation])
{
-// COUNTLY_LOG(@"Interface orientation is still same: %@", self.lastInterfaceOrientation);
+ CLY_LOG_V(@"Interface orientation is still same: %@", self.lastInterfaceOrientation);
return;
}
- COUNTLY_LOG(@"Interface orientation is now: %@", mode);
+ CLY_LOG_D(@"Interface orientation is now: %@", mode);
self.lastInterfaceOrientation = mode;
if (!CountlyConsentManager.sharedInstance.consentForUserDetails)
@@ -413,7 +428,7 @@ @implementation CLYWCSessionDelegateInterceptor
#if (TARGET_OS_WATCH)
- (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary *)userInfo
{
- COUNTLY_LOG(@"Watch received user info: \n%@", userInfo);
+ CLY_LOG_D(@"Watch received user info: \n%@", userInfo);
NSString* parentDeviceID = userInfo[kCountlyParentDeviceIDTransferKey];
@@ -421,14 +436,14 @@ - (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary
-@required
-- (void)internalLog:(NSString *)log;
+- (void)internalLog:(NSString *)log withLevel:(CLYInternalLogLevel)level;
+@optional
+- (void)internalLog:(NSString *)log DEPRECATED_MSG_ATTRIBUTE("Use 'internalLog:withLevel:' method instead!");
@end
@@ -129,10 +142,16 @@ extern CLYMetricKey const CLYMetricKeyInstalledWatchApp;
/**
* For receiving SDK's internal logs even in production builds.
* @discussion If set, SDK will forward its internal logs to this delegate object regardless of @c enableDebug initial config value.
- * @discussion @c internalLog: method declared as @c required in @c CountlyLoggerDelegate protocol will be called with log @c NSString.
+ * @discussion @c internalLog:withLevel: method declared as @c required in @c CountlyLoggerDelegate protocol will be called with log @c NSString.
*/
@property (nonatomic, weak) id loggerDelegate;
+/**
+ * For deciding which level SDK's internal logs should be printed at.
+ * @discussion Default value is @c CLYInternalLogLevelDebug.
+ */
+@property (nonatomic) CLYInternalLogLevel internalLogLevel;
+
#pragma mark -
/**
@@ -283,7 +302,7 @@ extern CLYMetricKey const CLYMetricKeyInstalledWatchApp;
/**
* Event send threshold is used for sending queued events to Countly Server when number of recorded events reaches to it, without waiting for next update session defined by @c updateSessionPeriod.
- * @discussion If not set, it will be 10 for @c iOS, @c tvOS & @c macOS, and 3 for @c watchOS by default.
+ * @discussion If not set, it will be 100 by default.
*/
@property (nonatomic) NSUInteger eventSendThreshold;
@@ -344,6 +363,7 @@ extern CLYMetricKey const CLYMetricKeyInstalledWatchApp;
* Crash log limit is used for limiting the number of crash logs to be stored on the device.
* @discussion If number of stored crash logs reaches @c crashLogLimit, SDK will start to drop oldest crash log while appending the newest one.
* @discussion If not set, it will be 100 by default.
+ * @discussion If @c shouldUsePLCrashReporter flag is set on initial config, this limit will not be applied.
*/
@property (nonatomic) NSUInteger crashLogLimit;
diff --git a/src/ios/CountlyiOS/CountlyConfig.m b/src/ios/CountlyiOS/CountlyConfig.m
index 175c817..0fce334 100644
--- a/src/ios/CountlyiOS/CountlyConfig.m
+++ b/src/ios/CountlyiOS/CountlyConfig.m
@@ -45,17 +45,18 @@ - (instancetype)init
{
#if (TARGET_OS_WATCH)
self.updateSessionPeriod = 20.0;
- self.eventSendThreshold = 3;
#else
self.updateSessionPeriod = 60.0;
- self.eventSendThreshold = 10;
#endif
+ self.eventSendThreshold = 100;
self.storedRequestsLimit = 1000;
self.crashLogLimit = 100;
self.location = kCLLocationCoordinate2DInvalid;
self.URLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration;
+
+ self.internalLogLevel = CLYInternalLogLevelDebug;
}
return self;
diff --git a/src/ios/CountlyiOS/CountlyConnectionManager.m b/src/ios/CountlyiOS/CountlyConnectionManager.m
index e2b81f6..b94da56 100644
--- a/src/ios/CountlyiOS/CountlyConnectionManager.m
+++ b/src/ios/CountlyiOS/CountlyConnectionManager.m
@@ -89,49 +89,49 @@ - (instancetype)init
- (void)proceedOnQueue
{
- COUNTLY_LOG(@"Proceeding on queue...");
+ CLY_LOG_D(@"Proceeding on queue...");
if (self.connection)
{
- COUNTLY_LOG(@"Proceeding on queue is aborted: Already has a request in process!");
+ CLY_LOG_D(@"Proceeding on queue is aborted: Already has a request in process!");
return;
}
if (isCrashing)
{
- COUNTLY_LOG(@"Proceeding on queue is aborted: Application is crashing!");
+ CLY_LOG_D(@"Proceeding on queue is aborted: Application is crashing!");
return;
}
if (self.isTerminating)
{
- COUNTLY_LOG(@"Proceeding on queue is aborted: Application is terminating!");
+ CLY_LOG_D(@"Proceeding on queue is aborted: Application is terminating!");
return;
}
if (self.customHeaderFieldName && !self.customHeaderFieldValue)
{
- COUNTLY_LOG(@"Proceeding on queue is aborted: customHeaderFieldName specified on config, but customHeaderFieldValue not set yet!");
+ CLY_LOG_D(@"Proceeding on queue is aborted: customHeaderFieldName specified on config, but customHeaderFieldValue not set yet!");
return;
}
if (CountlyPersistency.sharedInstance.isQueueBeingModified)
{
- COUNTLY_LOG(@"Proceeding on queue is aborted: Queue is being modified!");
+ CLY_LOG_D(@"Proceeding on queue is aborted: Queue is being modified!");
return;
}
NSString* firstItemInQueue = [CountlyPersistency.sharedInstance firstItemInQueue];
if (!firstItemInQueue)
{
- COUNTLY_LOG(@"Queue is empty. All requests are processed.");
+ CLY_LOG_D(@"Queue is empty. All requests are processed.");
return;
}
NSString* temporaryDeviceIDQueryString = [NSString stringWithFormat:@"&%@=%@", kCountlyQSKeyDeviceID, CLYTemporaryDeviceID];
if ([firstItemInQueue containsString:temporaryDeviceIDQueryString])
{
- COUNTLY_LOG(@"Proceeding on queue is aborted: Device ID in request is CLYTemporaryDeviceID!");
+ CLY_LOG_D(@"Proceeding on queue is aborted: Device ID in request is CLYTemporaryDeviceID!");
return;
}
@@ -169,11 +169,13 @@ - (void)proceedOnQueue
{
self.connection = nil;
+ CLY_LOG_V(@"Approximate received data size for request <%p> is %ld bytes.", (id)request, (long)data.length);
+
if (!error)
{
- if ([self isRequestSuccessful:response])
+ if ([self isRequestSuccessful:response data:data])
{
- COUNTLY_LOG(@"Request <%p> successfully completed.", request);
+ CLY_LOG_D(@"Request <%p> successfully completed.", request);
[CountlyPersistency.sharedInstance removeFromQueue:firstItemInQueue];
@@ -183,12 +185,12 @@ - (void)proceedOnQueue
}
else
{
- COUNTLY_LOG(@"Request <%p> failed!\nServer reply: %@", request, [data cly_stringUTF8]);
+ CLY_LOG_D(@"Request <%p> failed!\nServer reply: %@", request, [data cly_stringUTF8]);
}
}
else
{
- COUNTLY_LOG(@"Request <%p> failed!\nError: %@", request, error);
+ CLY_LOG_D(@"Request <%p> failed!\nError: %@", request, error);
#if (TARGET_OS_WATCH)
[CountlyPersistency.sharedInstance saveToFile];
#endif
@@ -197,7 +199,25 @@ - (void)proceedOnQueue
[self.connection resume];
- COUNTLY_LOG(@"Request <%p> started:\n[%@] %@ \n%@", (id)request, request.HTTPMethod, request.URL.absoluteString, request.HTTPBody ? ([request.HTTPBody cly_stringUTF8] ?: @"Picture uploading...") : @"");
+ [self logRequest:request];
+}
+
+- (void)logRequest:(NSURLRequest *)request
+{
+ NSString* bodyAsString = @"";
+ NSInteger sentSize = request.URL.absoluteString.length;
+
+ if (request.HTTPBody)
+ {
+ bodyAsString = [request.HTTPBody cly_stringUTF8];
+ if (!bodyAsString)
+ bodyAsString = @"Picture uploading...";
+
+ sentSize += request.HTTPBody.length;
+ }
+
+ CLY_LOG_D(@"Request <%p> started:\n[%@] %@ \n%@", (id)request, request.HTTPMethod, request.URL.absoluteString, bodyAsString);
+ CLY_LOG_V(@"Approximate sent data size for request <%p> is %ld bytes.", (id)request, (long)sentSize);
}
#pragma mark ---
@@ -322,7 +342,7 @@ - (void)sendCrashReport:(NSString *)report immediately:(BOOL)immediately;
{
if (!report)
{
- COUNTLY_LOG(@"Crash report is nil. Converting to JSON may have failed due to custom objects in initial config's crashSegmentation property.");
+ CLY_LOG_W(@"Crash report is nil. Converting to JSON may have failed due to custom objects in initial config's crashSegmentation property.");
return;
}
@@ -346,7 +366,7 @@ - (void)sendCrashReport:(NSString *)report immediately:(BOOL)immediately;
if (self.customHeaderFieldName && !self.customHeaderFieldValue)
{
- COUNTLY_LOG(@"customHeaderFieldName specified on config, but customHeaderFieldValue not set! Crash report stored to be sent later!");
+ CLY_LOG_D(@"customHeaderFieldName specified on config, but customHeaderFieldValue not set! Crash report stored to be sent later!");
[CountlyPersistency.sharedInstance addToQueue:queryString];
[CountlyPersistency.sharedInstance saveToFileSync];
@@ -355,7 +375,7 @@ - (void)sendCrashReport:(NSString *)report immediately:(BOOL)immediately;
if (CountlyDeviceInfo.sharedInstance.isDeviceIDTemporary)
{
- COUNTLY_LOG(@"Device ID is set as CLYTemporaryDeviceID! Crash report stored to be sent later!");
+ CLY_LOG_D(@"Device ID is set as CLYTemporaryDeviceID! Crash report stored to be sent later!");
[CountlyPersistency.sharedInstance addToQueue:queryString];
[CountlyPersistency.sharedInstance saveToFileSync];
@@ -376,22 +396,22 @@ - (void)sendCrashReport:(NSString *)report immediately:(BOOL)immediately;
[[self.URLSession dataTaskWithRequest:request completionHandler:^(NSData* data, NSURLResponse* response, NSError* error)
{
- if (error || ![self isRequestSuccessful:response])
+ if (error || ![self isRequestSuccessful:response data:data])
{
- COUNTLY_LOG(@"Crash Report Request <%p> failed!\n%@: %@", request, error ? @"Error" : @"Server reply", error ?: [data cly_stringUTF8]);
+ CLY_LOG_D(@"Request <%p> failed!\n%@: %@", request, error ? @"Error" : @"Server reply", error ?: [data cly_stringUTF8]);
[CountlyPersistency.sharedInstance addToQueue:queryString];
[CountlyPersistency.sharedInstance saveToFileSync];
}
else
{
- COUNTLY_LOG(@"Crash Report Request <%p> successfully completed.", request);
+ CLY_LOG_D(@"Request <%p> successfully completed.", request);
}
dispatch_semaphore_signal(semaphore);
}] resume];
- COUNTLY_LOG(@"Crash Report Request <%p> started:\n[%@] %@ \n%@", (id)request, request.HTTPMethod, request.URL.absoluteString, [request.HTTPBody cly_stringUTF8]);
+ [self logRequest:request];
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
@@ -526,24 +546,27 @@ - (NSData *)pictureUploadDataForQueryString:(NSString *)queryString
if (!localPicturePath.length)
return nil;
- COUNTLY_LOG(@"Local picture path successfully extracted from query string: %@", localPicturePath);
+ CLY_LOG_D(@"Local picture path successfully extracted from query string: %@", localPicturePath);
NSArray* allowedFileTypes = @[@"gif", @"png", @"jpg", @"jpeg"];
NSString* fileExt = localPicturePath.pathExtension.lowercaseString;
NSInteger fileExtIndex = [allowedFileTypes indexOfObject:fileExt];
if (fileExtIndex == NSNotFound)
+ {
+ CLY_LOG_W(@"Unsupported file extension for picture upload: %@", fileExt);
return nil;
+ }
NSData* imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:localPicturePath]];
if (!imageData)
{
- COUNTLY_LOG(@"Local picture data can not be read!");
+ CLY_LOG_W(@"Local picture data can not be read!");
return nil;
}
- COUNTLY_LOG(@"Local picture data read successfully.");
+ CLY_LOG_D(@"Local picture data read successfully.");
//NOTE: Overcome failing PNG file upload if data is directly read from disk
if (fileExtIndex == 1)
@@ -580,14 +603,41 @@ - (NSString *)appendChecksum:(NSString *)queryString
return queryString;
}
-- (BOOL)isRequestSuccessful:(NSURLResponse *)response
+- (BOOL)isRequestSuccessful:(NSURLResponse *)response data:(NSData *)data
{
if (!response)
return NO;
NSInteger code = ((NSHTTPURLResponse*)response).statusCode;
- return (code >= 200 && code < 300);
+ if (code >= 200 && code < 300)
+ {
+ NSError* error = nil;
+ NSDictionary* serverReply = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
+
+ if (error)
+ {
+ CLY_LOG_W(@"Server reply is not a valid JSON!");
+ return NO;
+ }
+
+ NSString* result = serverReply[@"result"];
+ if ([result isEqualToString:@"Success"])
+ {
+ CLY_LOG_V(@"Value for `result` key in server reply is `Success`.");
+ return YES;
+ }
+ else
+ {
+ CLY_LOG_V(@"Value for `result` key in server reply is not `Success`.");
+ return NO;
+ }
+ }
+ else
+ {
+ CLY_LOG_V(@"HTTP status code is not 2XX series.");
+ return NO;
+ }
}
- (NSInteger)sessionLengthInSeconds
@@ -608,7 +658,7 @@ - (NSURLSession *)URLSession
{
if (self.pinnedCertificates)
{
- COUNTLY_LOG(@"%d pinned certificate(s) specified in config.", (int)self.pinnedCertificates.count);
+ CLY_LOG_D(@"%d pinned certificate(s) specified in config.", (int)self.pinnedCertificates.count);
_URLSession = [NSURLSession sessionWithConfiguration:self.URLSessionConfiguration delegate:self delegateQueue:nil];
}
else
@@ -644,7 +694,7 @@ - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticat
if (serverKey != NULL && localKey != NULL && [(__bridge id)serverKey isEqual:(__bridge id)localKey])
{
- COUNTLY_LOG(@"Pinned certificate and server certificate match.");
+ CLY_LOG_D(@"Pinned certificate and server certificate match.");
isLocalAndServerCertMatch = YES;
CFRelease(localKey);
@@ -660,18 +710,18 @@ - (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticat
if (isLocalAndServerCertMatch && isServerCertValid)
{
- COUNTLY_LOG(@"Pinned certificate check is successful. Proceeding with request.");
+ CLY_LOG_D(@"Pinned certificate check is successful. Proceeding with request.");
completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:serverTrust]);
}
else
{
if (!isLocalAndServerCertMatch)
- COUNTLY_LOG(@"Pinned certificate and server certificate does not match!");
+ CLY_LOG_W(@"Pinned certificate and server certificate does not match!");
if (!isServerCertValid)
- COUNTLY_LOG(@"Server certificate is not valid! SecTrustEvaluate result is: %u", serverTrustResult);
+ CLY_LOG_W(@"Server certificate is not valid! SecTrustEvaluate result is: %u", serverTrustResult);
- COUNTLY_LOG(@"Pinned certificate check failed! Cancelling request.");
+ CLY_LOG_D(@"Pinned certificate check failed! Cancelling request.");
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, NULL);
}
diff --git a/src/ios/CountlyiOS/CountlyConsentManager.m b/src/ios/CountlyiOS/CountlyConsentManager.m
index 69acd1e..636826c 100644
--- a/src/ios/CountlyiOS/CountlyConsentManager.m
+++ b/src/ios/CountlyiOS/CountlyConsentManager.m
@@ -239,14 +239,14 @@ - (void)setConsentForSessions:(BOOL)consentForSessions
if (consentForSessions)
{
- COUNTLY_LOG(@"Consent for Session is given.");
+ CLY_LOG_D(@"Consent for Session is given.");
if (!CountlyCommon.sharedInstance.manualSessionHandling)
[CountlyConnectionManager.sharedInstance beginSession];
}
else
{
- COUNTLY_LOG(@"Consent for Session is cancelled.");
+ CLY_LOG_D(@"Consent for Session is cancelled.");
}
self.consentChanges[CLYConsentSessions] = @(consentForSessions);
@@ -259,11 +259,11 @@ - (void)setConsentForEvents:(BOOL)consentForEvents
if (consentForEvents)
{
- COUNTLY_LOG(@"Consent for Events is given.");
+ CLY_LOG_D(@"Consent for Events is given.");
}
else
{
- COUNTLY_LOG(@"Consent for Events is cancelled.");
+ CLY_LOG_D(@"Consent for Events is cancelled.");
[CountlyConnectionManager.sharedInstance sendEvents];
[CountlyPersistency.sharedInstance clearAllTimedEvents];
@@ -279,11 +279,11 @@ - (void)setConsentForUserDetails:(BOOL)consentForUserDetails
if (consentForUserDetails)
{
- COUNTLY_LOG(@"Consent for UserDetails is given.");
+ CLY_LOG_D(@"Consent for UserDetails is given.");
}
else
{
- COUNTLY_LOG(@"Consent for UserDetails is cancelled.");
+ CLY_LOG_D(@"Consent for UserDetails is cancelled.");
[CountlyUserDetails.sharedInstance clearUserDetails];
}
@@ -298,13 +298,13 @@ - (void)setConsentForCrashReporting:(BOOL)consentForCrashReporting
if (consentForCrashReporting)
{
- COUNTLY_LOG(@"Consent for CrashReporting is given.");
+ CLY_LOG_D(@"Consent for CrashReporting is given.");
[CountlyCrashReporter.sharedInstance startCrashReporting];
}
else
{
- COUNTLY_LOG(@"Consent for CrashReporting is cancelled.");
+ CLY_LOG_D(@"Consent for CrashReporting is cancelled.");
[CountlyCrashReporter.sharedInstance stopCrashReporting];
}
@@ -320,7 +320,7 @@ - (void)setConsentForPushNotifications:(BOOL)consentForPushNotifications
#if (TARGET_OS_IOS || TARGET_OS_OSX)
if (consentForPushNotifications)
{
- COUNTLY_LOG(@"Consent for PushNotifications is given.");
+ CLY_LOG_D(@"Consent for PushNotifications is given.");
#ifndef COUNTLY_EXCLUDE_PUSHNOTIFICATIONS
[CountlyPushNotifications.sharedInstance startPushNotifications];
@@ -328,7 +328,7 @@ - (void)setConsentForPushNotifications:(BOOL)consentForPushNotifications
}
else
{
- COUNTLY_LOG(@"Consent for PushNotifications is cancelled.");
+ CLY_LOG_D(@"Consent for PushNotifications is cancelled.");
#ifndef COUNTLY_EXCLUDE_PUSHNOTIFICATIONS
[CountlyPushNotifications.sharedInstance stopPushNotifications];
#endif
@@ -345,13 +345,13 @@ - (void)setConsentForLocation:(BOOL)consentForLocation
if (consentForLocation)
{
- COUNTLY_LOG(@"Consent for Location is given.");
+ CLY_LOG_D(@"Consent for Location is given.");
[CountlyLocationManager.sharedInstance sendLocationInfo];
}
else
{
- COUNTLY_LOG(@"Consent for Location is cancelled.");
+ CLY_LOG_D(@"Consent for Location is cancelled.");
}
self.consentChanges[CLYConsentLocation] = @(consentForLocation);
@@ -365,13 +365,13 @@ - (void)setConsentForViewTracking:(BOOL)consentForViewTracking
#if (TARGET_OS_IOS || TARGET_OS_TV)
if (consentForViewTracking)
{
- COUNTLY_LOG(@"Consent for ViewTracking is given.");
+ CLY_LOG_D(@"Consent for ViewTracking is given.");
[CountlyViewTracking.sharedInstance startAutoViewTracking];
}
else
{
- COUNTLY_LOG(@"Consent for ViewTracking is cancelled.");
+ CLY_LOG_D(@"Consent for ViewTracking is cancelled.");
[CountlyViewTracking.sharedInstance stopAutoViewTracking];
}
@@ -387,13 +387,13 @@ - (void)setConsentForAttribution:(BOOL)consentForAttribution
if (consentForAttribution)
{
- COUNTLY_LOG(@"Consent for Attribution is given.");
+ CLY_LOG_D(@"Consent for Attribution is given.");
[CountlyConnectionManager.sharedInstance sendAttribution];
}
else
{
- COUNTLY_LOG(@"Consent for Attribution is cancelled.");
+ CLY_LOG_D(@"Consent for Attribution is cancelled.");
}
self.consentChanges[CLYConsentAttribution] = @(consentForAttribution);
@@ -407,13 +407,13 @@ - (void)setConsentForAppleWatch:(BOOL)consentForAppleWatch
#if (TARGET_OS_IOS || TARGET_OS_WATCH)
if (consentForAppleWatch)
{
- COUNTLY_LOG(@"Consent for AppleWatch is given.");
+ CLY_LOG_D(@"Consent for AppleWatch is given.");
[CountlyCommon.sharedInstance startAppleWatchMatching];
}
else
{
- COUNTLY_LOG(@"Consent for AppleWatch is cancelled.");
+ CLY_LOG_D(@"Consent for AppleWatch is cancelled.");
}
#endif
@@ -428,13 +428,13 @@ - (void)setConsentForPerformanceMonitoring:(BOOL)consentForPerformanceMonitoring
#if (TARGET_OS_IOS)
if (consentForPerformanceMonitoring)
{
- COUNTLY_LOG(@"Consent for PerformanceMonitoring is given.");
+ CLY_LOG_D(@"Consent for PerformanceMonitoring is given.");
[CountlyPerformanceMonitoring.sharedInstance startPerformanceMonitoring];
}
else
{
- COUNTLY_LOG(@"Consent for PerformanceMonitoring is cancelled.");
+ CLY_LOG_D(@"Consent for PerformanceMonitoring is cancelled.");
[CountlyPerformanceMonitoring.sharedInstance stopPerformanceMonitoring];
}
@@ -450,13 +450,13 @@ - (void)setConsentForFeedback:(BOOL)consentForFeedback
#if (TARGET_OS_IOS)
if (consentForFeedback)
{
- COUNTLY_LOG(@"Consent for Feedback is given.");
+ CLY_LOG_D(@"Consent for Feedback is given.");
[CountlyFeedbacks.sharedInstance checkForStarRatingAutoAsk];
}
else
{
- COUNTLY_LOG(@"Consent for Feedback is cancelled.");
+ CLY_LOG_D(@"Consent for Feedback is cancelled.");
}
#endif
@@ -469,13 +469,13 @@ - (void)setConsentForRemoteConfig:(BOOL)consentForRemoteConfig
if (consentForRemoteConfig)
{
- COUNTLY_LOG(@"Consent for RemoteConfig is given.");
+ CLY_LOG_D(@"Consent for RemoteConfig is given.");
[CountlyRemoteConfig.sharedInstance startRemoteConfig];
}
else
{
- COUNTLY_LOG(@"Consent for RemoteConfig is cancelled.");
+ CLY_LOG_D(@"Consent for RemoteConfig is cancelled.");
}
self.consentChanges[CLYConsentRemoteConfig] = @(consentForRemoteConfig);
diff --git a/src/ios/CountlyiOS/CountlyCrashReporter.h b/src/ios/CountlyiOS/CountlyCrashReporter.h
index 7906709..e18b9d7 100644
--- a/src/ios/CountlyiOS/CountlyCrashReporter.h
+++ b/src/ios/CountlyiOS/CountlyCrashReporter.h
@@ -21,6 +21,7 @@
- (void)stopCrashReporting;
- (void)recordException:(NSException *)exception withStackTrace:(NSArray *)stackTrace isFatal:(BOOL)isFatal;
- (void)log:(NSString *)log;
+- (void)clearCrashLogs;
@end
diff --git a/src/ios/CountlyiOS/CountlyCrashReporter.m b/src/ios/CountlyiOS/CountlyCrashReporter.m
index e42d7b0..91c06e7 100644
--- a/src/ios/CountlyiOS/CountlyCrashReporter.m
+++ b/src/ios/CountlyiOS/CountlyCrashReporter.m
@@ -135,7 +135,7 @@ - (void)stopCrashReporting
signal(SIGTRAP, SIG_DFL);
#endif
- self.customCrashLogs = nil;
+ [self clearCrashLogs];
}
#ifdef COUNTLY_PLCRASHREPORTER_EXISTS
@@ -162,14 +162,14 @@ - (void)handlePendingCrashReport
NSData* crashData = [self.crashReporter loadPendingCrashReportDataAndReturnError:&error];
if (!crashData)
{
- COUNTLY_LOG(@"Could not load crash report data: %@", error);
+ CLY_LOG_W(@"Could not load crash report data: %@", error);
return;
}
PLCrashReport *report = [PLCrashReport.alloc initWithData:crashData error:&error];
if (!report)
{
- COUNTLY_LOG(@"Could not initialize crash report using data %@", error);
+ CLY_LOG_W(@"Could not initialize crash report using data %@", error);
return;
}
@@ -188,13 +188,13 @@ - (void)handlePendingCrashReport
BOOL shouldSend = YES;
if (self.shouldSendCrashReportCallback)
{
- COUNTLY_LOG(@"shouldSendCrashReportCallback is set, asking it if the report should be sent or not.");
+ CLY_LOG_D(@"shouldSendCrashReportCallback is set, asking it if the report should be sent or not.");
shouldSend = self.shouldSendCrashReportCallback(crashReport);
if (shouldSend)
- COUNTLY_LOG(@"shouldSendCrashReportCallback returned YES, sending the report.");
+ CLY_LOG_D(@"shouldSendCrashReportCallback returned YES, sending the report.");
else
- COUNTLY_LOG(@"shouldSendCrashReportCallback returned NO, not sending the report.");
+ CLY_LOG_D(@"shouldSendCrashReportCallback returned NO, not sending the report.");
}
if (shouldSend)
@@ -294,7 +294,7 @@ void CountlyExceptionHandler(NSException *exception, bool isFatal, bool isAutoDe
}
else
{
- COUNTLY_LOG(@"Crash matches filter and it will not be processed.");
+ CLY_LOG_D(@"Crash matches filter and it will not be processed.");
}
if (isAutoDetect)
@@ -353,6 +353,18 @@ - (void)log:(NSString *)log
}
}
+- (void)clearCrashLogs
+{
+ if (self.shouldUsePLCrashReporter)
+ {
+ [CountlyPersistency.sharedInstance deleteCustomCrashLogFile];
+ }
+ else
+ {
+ [self.customCrashLogs removeAllObjects];
+ }
+}
+
- (NSDictionary *)binaryImagesForStackTrace:(NSArray *)stackTrace
{
NSMutableSet* binaryImagesInStack = NSMutableSet.new;
@@ -376,7 +388,7 @@ - (NSDictionary *)binaryImagesForStackTrace:(NSArray *)stackTrace
const char* imageNameChar = _dyld_get_image_name(i);
if (imageNameChar == NULL)
{
- COUNTLY_LOG(@"Image Name can not be retrieved!");
+ CLY_LOG_W(@"Image Name can not be retrieved!");
continue;
}
@@ -384,16 +396,16 @@ - (NSDictionary *)binaryImagesForStackTrace:(NSArray *)stackTrace
if (![binaryImagesInStack containsObject:imageName])
{
- //NOTE: Image Name is not in the stack trace, so it will be ignored!
+ CLY_LOG_V(@"Image Name is not in the stack trace, so it will be ignored!\n%@", imageName);
continue;
}
- COUNTLY_LOG(@"Image Name is in the stack trace, so it will be used!\n%@", imageName);
+ CLY_LOG_D(@"Image Name is in the stack trace, so it will be used!\n%@", imageName);
const struct mach_header* imageHeader = _dyld_get_image_header(i);
if (imageHeader == NULL)
{
- COUNTLY_LOG(@"Image Header can not be retrieved!");
+ CLY_LOG_W(@"Image Header can not be retrieved!");
continue;
}
@@ -416,7 +428,7 @@ - (NSDictionary *)binaryImagesForStackTrace:(NSArray *)stackTrace
if (!imageUUID)
{
- COUNTLY_LOG(@"Image UUID can not be retrieved!");
+ CLY_LOG_W(@"Image UUID can not be retrieved!");
continue;
}
diff --git a/src/ios/CountlyiOS/CountlyDeviceInfo.m b/src/ios/CountlyiOS/CountlyDeviceInfo.m
index cee9bdd..18824ca 100644
--- a/src/ios/CountlyiOS/CountlyDeviceInfo.m
+++ b/src/ios/CountlyiOS/CountlyDeviceInfo.m
@@ -13,8 +13,10 @@
#include
#if (TARGET_OS_IOS)
+#if (!TARGET_OS_MACCATALYST)
#import
#import
+#endif
#elif (TARGET_OS_OSX)
#import
#endif
@@ -31,11 +33,14 @@
CLYMetricKey const CLYMetricKeyHasWatch = @"_has_watch";
CLYMetricKey const CLYMetricKeyInstalledWatchApp = @"_installed_watch_app";
-#if (TARGET_OS_IOS)
@interface CountlyDeviceInfo ()
+@property (nonatomic) BOOL isInBackground;
+#if (TARGET_OS_IOS)
+#if (!TARGET_OS_MACCATALYST)
@property (nonatomic) CTTelephonyNetworkInfo* networkInfo;
-@end
#endif
+#endif
+@end
@implementation CountlyDeviceInfo
@@ -53,13 +58,41 @@ - (instancetype)init
{
self.deviceID = [CountlyPersistency.sharedInstance retrieveDeviceID];
#if (TARGET_OS_IOS)
+#if (!TARGET_OS_MACCATALYST)
self.networkInfo = CTTelephonyNetworkInfo.new;
+#endif
+#endif
+
+#if (TARGET_OS_IOS || TARGET_OS_TV)
+ self.isInBackground = (UIApplication.sharedApplication.applicationState == UIApplicationStateBackground);
+
+ [NSNotificationCenter.defaultCenter addObserver:self
+ selector:@selector(applicationDidEnterBackground:)
+ name:UIApplicationDidEnterBackgroundNotification
+ object:nil];
+
+ [NSNotificationCenter.defaultCenter addObserver:self
+ selector:@selector(applicationWillEnterForeground:)
+ name:UIApplicationWillEnterForegroundNotification
+ object:nil];
#endif
}
return self;
}
+//NOTE: Using this flag instead of a direct call to UIApplication's applicationState method
+// in order to avoid making a UI call on a non-main thread at the moment of a crash.
+- (void)applicationDidEnterBackground:(NSNotification *)notification
+{
+ self.isInBackground = YES;
+}
+
+- (void)applicationWillEnterForeground:(NSNotification *)notification
+{
+ self.isInBackground = NO;
+}
+
- (void)initializeDeviceID:(NSString *)deviceID
{
self.deviceID = [self ensafeDeviceID:deviceID];
@@ -112,10 +145,14 @@ + (NSString *)device
+ (NSString *)deviceType
{
#if (TARGET_OS_IOS)
+#if (TARGET_OS_MACCATALYST)
+ return @"desktop";
+#else
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
return @"tablet";
return @"mobile";
+#endif
#elif (TARGET_OS_WATCH)
return @"wearable";
#elif (TARGET_OS_TV)
@@ -179,7 +216,9 @@ + (NSString *)osVersion
+ (NSString *)carrier
{
#if (TARGET_OS_IOS)
+#if (!TARGET_OS_MACCATALYST)
return CountlyDeviceInfo.sharedInstance.networkInfo.subscriberCellularProvider.carrierName;
+#endif
#endif
//NOTE: it is not possible to get carrier info on Apple Watches as CoreTelephony is not available.
return nil;
@@ -324,6 +363,7 @@ + (NSUInteger)connectionType
connType = CLYConnectionCellNetwork;
#if (TARGET_OS_IOS)
+#if (!TARGET_OS_MACCATALYST)
NSDictionary* connectionTypes =
@{
CTRadioAccessTechnologyGPRS: @(CLYConnectionCellNetwork2G),
@@ -342,6 +382,7 @@ + (NSUInteger)connectionType
NSString* radioAccessTech = CountlyDeviceInfo.sharedInstance.networkInfo.currentRadioAccessTechnology;
if (connectionTypes[radioAccessTech])
connType = [connectionTypes[radioAccessTech] integerValue];
+#endif
#endif
}
else if ([[NSString stringWithUTF8String:i->ifa_name] isEqualToString:@"en0"])
@@ -359,7 +400,7 @@ + (NSUInteger)connectionType
}
@catch (NSException *exception)
{
- COUNTLY_LOG(@"Connection type can not be retrieved: \n%@", exception);
+ CLY_LOG_W(@"Connection type can not be retrieved: \n%@", exception);
}
return connType;
@@ -452,11 +493,7 @@ + (BOOL)isJailbroken
+ (BOOL)isInBackground
{
-#if (TARGET_OS_IOS || TARGET_OS_TV)
- return UIApplication.sharedApplication.applicationState == UIApplicationStateBackground;
-#else
- return NO;
-#endif
+ return CountlyDeviceInfo.sharedInstance.isInBackground;
}
@end
diff --git a/src/ios/CountlyiOS/CountlyFeedbackWidget.h b/src/ios/CountlyiOS/CountlyFeedbackWidget.h
index aa80e53..5e5b1eb 100644
--- a/src/ios/CountlyiOS/CountlyFeedbackWidget.h
+++ b/src/ios/CountlyiOS/CountlyFeedbackWidget.h
@@ -20,6 +20,12 @@ extern CLYFeedbackWidgetType const CLYFeedbackWidgetTypeNPS;
@property (nonatomic, readonly) NSString* ID;
@property (nonatomic, readonly) NSString* name;
+
+/**
+ * Modally presents the feedback widget above the top visible view controller.
+ * @discussion Calls to this method will be ignored if consent for @c CLYConsentFeedback is not given
+ * while @c requiresConsent flag is set on initial configuration.
+ */
- (void)present;
#endif
diff --git a/src/ios/CountlyiOS/CountlyFeedbacks.m b/src/ios/CountlyiOS/CountlyFeedbacks.m
index ba1d035..6b28de9 100644
--- a/src/ios/CountlyiOS/CountlyFeedbacks.m
+++ b/src/ios/CountlyiOS/CountlyFeedbacks.m
@@ -114,7 +114,7 @@ - (void)showDialog:(void(^)(NSInteger rating))completion
}
@catch (NSException* exception)
{
- COUNTLY_LOG(@"UIAlertController's contentViewController can not be set: \n%@", exception);
+ CLY_LOG_W(@"UIAlertController's contentViewController can not be set: \n%@", exception);
}
[CountlyCommon.sharedInstance tryPresentingViewController:self.alertController];
@@ -139,7 +139,7 @@ - (void)checkForStarRatingAutoAsk
if (self.sessionCount == sessionCountSoFar)
{
- COUNTLY_LOG(@"Asking for star-rating as session count reached specified limit %d ...", (int)self.sessionCount);
+ CLY_LOG_D(@"Asking for star-rating as session count reached specified limit %d ...", (int)self.sessionCount);
[self showDialog:self.ratingCompletionForAutoAsk];
diff --git a/src/ios/CountlyiOS/CountlyLocationManager.m b/src/ios/CountlyiOS/CountlyLocationManager.m
index 11e4d5a..7b18c97 100644
--- a/src/ios/CountlyiOS/CountlyLocationManager.m
+++ b/src/ios/CountlyiOS/CountlyLocationManager.m
@@ -55,11 +55,11 @@ - (void)updateLocation:(CLLocationCoordinate2D)location city:(NSString *)city IS
if (self.city && !self.ISOCountryCode)
{
- COUNTLY_LOG(@"City and Country Code should be set as a pair. Country Code is missing while City is set!");
+ CLY_LOG_W(@"City and Country Code should be set as a pair. Country Code is missing while City is set!");
}
else if (self.ISOCountryCode && !self.city)
{
- COUNTLY_LOG(@"City and Country Code should be set as a pair. City is missing while Country Code is set!");
+ CLY_LOG_W(@"City and Country Code should be set as a pair. City is missing while Country Code is set!");
}
if ((self.location || self.city || self.ISOCountryCode || self.IP))
diff --git a/src/ios/CountlyiOS/CountlyPerformanceMonitoring.m b/src/ios/CountlyiOS/CountlyPerformanceMonitoring.m
index 8ca9ae2..a53eaa8 100644
--- a/src/ios/CountlyiOS/CountlyPerformanceMonitoring.m
+++ b/src/ios/CountlyiOS/CountlyPerformanceMonitoring.m
@@ -63,7 +63,7 @@ - (void)startPerformanceMonitoring
if (!CountlyConsentManager.sharedInstance.consentForPerformanceMonitoring)
return;
- COUNTLY_LOG(@"Starting performance monitoring...");
+ CLY_LOG_D(@"Starting performance monitoring...");
#if (TARGET_OS_OSX)
[NSNotificationCenter.defaultCenter addObserver:self selector:@selector(applicationDidBecomeActive:) name:NSApplicationDidBecomeActiveNotification object:nil];
@@ -96,14 +96,14 @@ - (void)stopPerformanceMonitoring
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
- COUNTLY_LOG(@"applicationDidBecomeActive: (Performance Monitoring)");
+ CLY_LOG_D(@"applicationDidBecomeActive: (Performance Monitoring)");
[self startForegroundTrace];
}
- (void)applicationWillResignActive:(NSNotification *)notification
{
- COUNTLY_LOG(@"applicationWillResignActive: (Performance Monitoring)");
+ CLY_LOG_D(@"applicationWillResignActive: (Performance Monitoring)");
[self startBackgroundTrace];
}
@@ -140,13 +140,13 @@ - (void)recordAppStartDurationTraceWithStartTime:(long long)startTime endTime:(l
if (self.hasAlreadyRecordedAppStartDurationTrace)
{
- COUNTLY_LOG(@"App start duration trace can be recorded once per app launch. So, it will not be recorded this time!");
+ CLY_LOG_W(@"App start duration trace can be recorded once per app launch. So, it will not be recorded this time!");
return;
}
long long appStartDuration = endTime - startTime;
- COUNTLY_LOG(@"App is loaded and displayed its first view in %lld milliseconds.", appStartDuration);
+ CLY_LOG_D(@"App is loaded and displayed its first view in %lld milliseconds.", appStartDuration);
NSDictionary* metrics =
@{
@@ -212,7 +212,7 @@ - (void)startCustomTrace:(NSString *)traceName
{
if (self.startedCustomTraces[traceName])
{
- COUNTLY_LOG(@"Custom trace with name '%@' already started!", traceName);
+ CLY_LOG_W(@"Custom trace with name '%@' already started!", traceName);
return;
}
@@ -220,7 +220,7 @@ - (void)startCustomTrace:(NSString *)traceName
self.startedCustomTraces[traceName] = startTime;
}
- COUNTLY_LOG(@"Custom trace with name '%@' just started!", traceName);
+ CLY_LOG_D(@"Custom trace with name '%@' just started!", traceName);
}
- (void)endCustomTrace:(NSString *)traceName metrics:(NSDictionary *)metrics
@@ -241,7 +241,7 @@ - (void)endCustomTrace:(NSString *)traceName metrics:(NSDictionary *)metrics
if (!startTime)
{
- COUNTLY_LOG(@"Custom trace with name '%@' not started yet or cancelled/ended before!", traceName);
+ CLY_LOG_W(@"Custom trace with name '%@' not started yet or cancelled/ended before!", traceName);
return;
}
@@ -263,7 +263,7 @@ - (void)endCustomTrace:(NSString *)traceName metrics:(NSDictionary *)metrics
kCountlyPMKeyEndTime: endTime,
};
- COUNTLY_LOG(@"Custom trace with name '%@' just ended with duration %lld ms.", traceName, duration);
+ CLY_LOG_D(@"Custom trace with name '%@' just ended with duration %lld ms.", traceName, duration);
[CountlyConnectionManager.sharedInstance sendPerformanceMonitoringTrace:[trace cly_JSONify]];
}
@@ -286,11 +286,11 @@ - (void)cancelCustomTrace:(NSString *)traceName
if (!startTime)
{
- COUNTLY_LOG(@"Custom trace with name '%@' not started yet or cancelled/ended before!", traceName);
+ CLY_LOG_W(@"Custom trace with name '%@' not started yet or cancelled/ended before!", traceName);
return;
}
- COUNTLY_LOG(@"Custom trace with name '%@' cancelled!", traceName);
+ CLY_LOG_D(@"Custom trace with name '%@' cancelled!", traceName);
}
- (void)clearAllCustomTraces
diff --git a/src/ios/CountlyiOS/CountlyPersistency.m b/src/ios/CountlyiOS/CountlyPersistency.m
index 70681c8..50d2a61 100644
--- a/src/ios/CountlyiOS/CountlyPersistency.m
+++ b/src/ios/CountlyiOS/CountlyPersistency.m
@@ -114,7 +114,7 @@ - (void)replaceAllTemporaryDeviceIDsInQueueWithDeviceID:(NSString *)deviceID
{
if ([queryString containsString:temporaryDeviceIDQueryString])
{
- COUNTLY_LOG(@"Detected a request with temporary device ID in queue and replaced it with real device ID.");
+ CLY_LOG_D(@"Detected a request with temporary device ID in queue and replaced it with real device ID.");
NSString * replacedQueryString = [queryString stringByReplacingOccurrencesOfString:temporaryDeviceIDQueryString withString:realDeviceIDQueryString];
self.queuedRequests[idx] = replacedQueryString;
}
@@ -134,7 +134,7 @@ - (void)replaceAllAppKeysInQueueWithCurrentAppKey
if (![appKeyInQueryString isEqualToString:CountlyConnectionManager.sharedInstance.appKey.cly_URLEscaped])
{
- COUNTLY_LOG(@"Detected a request with a different app key (%@) in queue and replaced it with current app key.", appKeyInQueryString);
+ CLY_LOG_D(@"Detected a request with a different app key (%@) in queue and replaced it with current app key.", appKeyInQueryString);
NSString* currentAppKeyQueryString = [NSString stringWithFormat:@"%@=%@", kCountlyQSKeyAppKey, CountlyConnectionManager.sharedInstance.appKey.cly_URLEscaped];
NSString* differentAppKeyQueryString = [NSString stringWithFormat:@"%@=%@", kCountlyQSKeyAppKey, appKeyInQueryString];
@@ -160,7 +160,7 @@ - (void)removeDifferentAppKeysFromQueue
BOOL isSameAppKey = [appKeyInQueryString isEqualToString:CountlyConnectionManager.sharedInstance.appKey.cly_URLEscaped];
if (!isSameAppKey)
{
- COUNTLY_LOG(@"Detected a request with a different app key (%@) in queue and removed it.", appKeyInQueryString);
+ CLY_LOG_D(@"Detected a request with a different app key (%@) in queue and removed it.", appKeyInQueryString);
}
return isSameAppKey;
@@ -220,7 +220,7 @@ - (void)recordTimedEvent:(CountlyEvent *)event
{
if (self.startedEvents[event.key])
{
- COUNTLY_LOG(@"Event with key '%@' already started!", event.key);
+ CLY_LOG_W(@"Event with key '%@' already started!", event.key);
return;
}
@@ -275,7 +275,7 @@ - (void)writeCustomCrashLogToFile:(NSString *)log
[line writeToFile:crashLogFileURL.path atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (error)
{
- COUNTLY_LOG(@"Crash Log File can not be created: \n%@", error);
+ CLY_LOG_W(@"Crash Log File can not be created: \n%@", error);
}
}
});
@@ -301,11 +301,11 @@ - (void)deleteCustomCrashLogFile
NSError* error = nil;
if ([NSFileManager.defaultManager fileExistsAtPath:crashLogFileURL.path])
{
- COUNTLY_LOG(@"Detected Crash Log File and deleting it.");
+ CLY_LOG_D(@"Detected Crash Log File and deleting it.");
[NSFileManager.defaultManager removeItemAtURL:crashLogFileURL error:&error];
if (error)
{
- COUNTLY_LOG(@"Crash Log File can not be deleted: \n%@", error);
+ CLY_LOG_W(@"Crash Log File can not be deleted: \n%@", error);
}
}
}
@@ -336,7 +336,7 @@ - (NSURL *)storageDirectoryURL
[NSFileManager.defaultManager createDirectoryAtURL:URL withIntermediateDirectories:YES attributes:nil error:&error];
if (error)
{
- COUNTLY_LOG(@"Application Support directory can not be created: \n%@", error);
+ CLY_LOG_W(@"Application Support directory can not be created: \n%@", error);
}
}
});
@@ -380,7 +380,7 @@ - (void)saveToFileSync
#pragma clang diagnostic ignored "-Wunused-variable"
BOOL writeResult = [saveData writeToFile:[self storageFileURL].path atomically:YES];
- COUNTLY_LOG(@"Result of writing data to file: %d", writeResult);
+ CLY_LOG_D(@"Result of writing data to file: %d", writeResult);
#pragma clang diagnostic pop
@@ -395,11 +395,11 @@ - (NSString* )retrieveDeviceID
if (retrievedDeviceID)
{
- COUNTLY_LOG(@"Device ID successfully retrieved from UserDefaults: %@", retrievedDeviceID);
+ CLY_LOG_D(@"Device ID successfully retrieved from UserDefaults: %@", retrievedDeviceID);
return retrievedDeviceID;
}
- COUNTLY_LOG(@"There is no stored Device ID in UserDefaults!");
+ CLY_LOG_D(@"There is no stored Device ID in UserDefaults!");
return nil;
}
@@ -409,7 +409,7 @@ - (void)storeDeviceID:(NSString *)deviceID
[NSUserDefaults.standardUserDefaults setObject:deviceID forKey:kCountlyStoredDeviceIDKey];
[NSUserDefaults.standardUserDefaults synchronize];
- COUNTLY_LOG(@"Device ID successfully stored in UserDefaults: %@", deviceID);
+ CLY_LOG_D(@"Device ID successfully stored in UserDefaults: %@", deviceID);
}
- (NSString *)retrieveNSUUID
diff --git a/src/ios/CountlyiOS/CountlyPushNotifications.m b/src/ios/CountlyiOS/CountlyPushNotifications.m
index c84390c..d3e5ab5 100644
--- a/src/ios/CountlyiOS/CountlyPushNotifications.m
+++ b/src/ios/CountlyiOS/CountlyPushNotifications.m
@@ -246,18 +246,18 @@ - (void)handleNotification:(NSDictionary *)notification
if (!CountlyConsentManager.sharedInstance.consentForPushNotifications)
return;
- COUNTLY_LOG(@"Handling remote notification %@", notification);
+ CLY_LOG_D(@"Handling remote notification %@", notification);
NSDictionary* countlyPayload = notification[kCountlyPNKeyCountlyPayload];
NSString* notificationID = countlyPayload[kCountlyPNKeyNotificationID];
if (!notificationID)
{
- COUNTLY_LOG(@"Countly payload not found in notification dictionary!");
+ CLY_LOG_D(@"Countly payload not found in notification dictionary!");
return;
}
- COUNTLY_LOG(@"Countly Push Notification ID: %@", notificationID);
+ CLY_LOG_D(@"Countly Push Notification ID: %@", notificationID);
#endif
#if (TARGET_OS_OSX)
@@ -268,14 +268,14 @@ - (void)handleNotification:(NSDictionary *)notification
#if (TARGET_OS_IOS)
if (self.doNotShowAlertForNotifications)
{
- COUNTLY_LOG(@"doNotShowAlertForNotifications flag is set!");
+ CLY_LOG_D(@"doNotShowAlertForNotifications flag is set!");
return;
}
if (@available(iOS 10.0, *))
{
//NOTE: On iOS10+ when a silent notification (content-available: 1) with `alert` key arrives, do not show alert here, as it is shown in UN framework delegate method
- COUNTLY_LOG(@"A silent notification (content-available: 1) with `alert` key on iOS10+.");
+ CLY_LOG_W(@"A silent notification (content-available: 1) with `alert` key on iOS10+.");
return;
}
@@ -296,7 +296,7 @@ - (void)handleNotification:(NSDictionary *)notification
if (!message && !title)
{
- COUNTLY_LOG(@"Title and Message are both not found in notification dictionary!");
+ CLY_LOG_W(@"Title and Message are both not found in notification dictionary!");
return;
}
@@ -411,8 +411,8 @@ - (void)recordActionEvent:(NSString *)notificationID buttonIndex:(NSInteger)butt
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler API_AVAILABLE(ios(10.0), macos(10.14))
{
- COUNTLY_LOG(@"userNotificationCenter:willPresentNotification:withCompletionHandler:");
- COUNTLY_LOG(@"%@", notification.request.content.userInfo.description);
+ CLY_LOG_D(@"userNotificationCenter:willPresentNotification:withCompletionHandler:");
+ CLY_LOG_D(@"%@", notification.request.content.userInfo.description);
if (!self.doNotShowAlertForNotifications)
{
@@ -433,8 +433,8 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNot
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler API_AVAILABLE(ios(10.0), macos(10.14))
{
- COUNTLY_LOG(@"userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:");
- COUNTLY_LOG(@"%@", response.notification.request.content.userInfo.description);
+ CLY_LOG_D(@"userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:");
+ CLY_LOG_D(@"%@", response.notification.request.content.userInfo.description);
if (CountlyConsentManager.sharedInstance.consentForPushNotifications)
{
@@ -446,7 +446,7 @@ - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNoti
NSInteger buttonIndex = 0;
NSString* URL = nil;
- COUNTLY_LOG(@"Action Identifier: %@", response.actionIdentifier);
+ CLY_LOG_D(@"Action Identifier: %@", response.actionIdentifier);
if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier])
{
@@ -504,7 +504,7 @@ @implementation NSObject (CountlyPushNotifications)
#if (TARGET_OS_IOS || TARGET_OS_OSX)
- (void)Countly_application:(CLYApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
- COUNTLY_LOG(@"App didRegisterForRemoteNotificationsWithDeviceToken: %@", deviceToken);
+ CLY_LOG_D(@"App didRegisterForRemoteNotificationsWithDeviceToken: %@", deviceToken);
const char* bytes = [deviceToken bytes];
NSMutableString *token = NSMutableString.new;
@@ -520,7 +520,7 @@ - (void)Countly_application:(CLYApplication *)application didRegisterForRemoteNo
- (void)Countly_application:(CLYApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
- COUNTLY_LOG(@"App didFailToRegisterForRemoteNotificationsWithError: %@", error);
+ CLY_LOG_D(@"App didFailToRegisterForRemoteNotificationsWithError: %@", error);
CountlyPushNotifications.sharedInstance.token = kCountlyTokenError;
@@ -533,7 +533,7 @@ - (void)Countly_application:(CLYApplication *)application didFailToRegisterForRe
#if (TARGET_OS_IOS)
- (void)Countly_application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
- COUNTLY_LOG(@"App didRegisterUserNotificationSettings: %@", notificationSettings);
+ CLY_LOG_D(@"App didRegisterUserNotificationSettings: %@", notificationSettings);
[CountlyPushNotifications.sharedInstance sendToken];
@@ -547,7 +547,7 @@ - (void)Countly_application:(UIApplication *)application didRegisterUserNotifica
- (void)Countly_application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;
{
- COUNTLY_LOG(@"App didReceiveRemoteNotification:fetchCompletionHandler");
+ CLY_LOG_D(@"App didReceiveRemoteNotification:fetchCompletionHandler");
[CountlyPushNotifications.sharedInstance handleNotification:userInfo];
@@ -557,7 +557,7 @@ - (void)Countly_application:(UIApplication *)application didReceiveRemoteNotific
#elif (TARGET_OS_OSX)
- (void)Countly_application:(NSApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
- COUNTLY_LOG(@"App didReceiveRemoteNotification:");
+ CLY_LOG_D(@"App didReceiveRemoteNotification:");
[CountlyPushNotifications.sharedInstance handleNotification:userInfo];
diff --git a/src/ios/CountlyiOS/CountlyRemoteConfig.m b/src/ios/CountlyiOS/CountlyRemoteConfig.m
index 70462b1..0de5539 100644
--- a/src/ios/CountlyiOS/CountlyRemoteConfig.m
+++ b/src/ios/CountlyiOS/CountlyRemoteConfig.m
@@ -50,20 +50,20 @@ - (void)startRemoteConfig
if (CountlyDeviceInfo.sharedInstance.isDeviceIDTemporary)
return;
- COUNTLY_LOG(@"Fetching remote config on start...");
+ CLY_LOG_D(@"Fetching remote config on start...");
[self fetchRemoteConfigForKeys:nil omitKeys:nil completionHandler:^(NSDictionary *remoteConfig, NSError *error)
{
if (!error)
{
- COUNTLY_LOG(@"Fetching remote config on start is successful. \n%@", remoteConfig);
+ CLY_LOG_D(@"Fetching remote config on start is successful. \n%@", remoteConfig);
self.cachedRemoteConfig = remoteConfig;
[CountlyPersistency.sharedInstance storeRemoteConfig:self.cachedRemoteConfig];
}
else
{
- COUNTLY_LOG(@"Fetching remote config on start failed: %@", error);
+ CLY_LOG_W(@"Fetching remote config on start failed: %@", error);
}
if (self.remoteConfigCompletionHandler)
@@ -79,13 +79,13 @@ - (void)updateRemoteConfigForKeys:(NSArray *)keys omitKeys:(NSArray *)omitKeys c
if (CountlyDeviceInfo.sharedInstance.isDeviceIDTemporary)
return;
- COUNTLY_LOG(@"Fetching remote config manually...");
+ CLY_LOG_D(@"Fetching remote config manually...");
[self fetchRemoteConfigForKeys:keys omitKeys:omitKeys completionHandler:^(NSDictionary *remoteConfig, NSError *error)
{
if (!error)
{
- COUNTLY_LOG(@"Fetching remote config manually is successful. \n%@", remoteConfig);
+ CLY_LOG_D(@"Fetching remote config manually is successful. \n%@", remoteConfig);
if (!keys && !omitKeys)
{
@@ -102,7 +102,7 @@ - (void)updateRemoteConfigForKeys:(NSArray *)keys omitKeys:(NSArray *)omitKeys c
}
else
{
- COUNTLY_LOG(@"Fetching remote config manually failed: %@", error);
+ CLY_LOG_W(@"Fetching remote config manually failed: %@", error);
}
if (completionHandler)
@@ -150,7 +150,7 @@ - (void)fetchRemoteConfigForKeys:(NSArray *)keys omitKeys:(NSArray *)omitKeys co
if (error)
{
- COUNTLY_LOG(@"Remote Config Request <%p> failed!\nError: %@", request, error);
+ CLY_LOG_D(@"Remote Config Request <%p> failed!\nError: %@", request, error);
dispatch_async(dispatch_get_main_queue(), ^
{
@@ -160,7 +160,7 @@ - (void)fetchRemoteConfigForKeys:(NSArray *)keys omitKeys:(NSArray *)omitKeys co
return;
}
- COUNTLY_LOG(@"Remote Config Request <%p> successfully completed.", request);
+ CLY_LOG_D(@"Remote Config Request <%p> successfully completed.", request);
dispatch_async(dispatch_get_main_queue(), ^
{
@@ -170,7 +170,7 @@ - (void)fetchRemoteConfigForKeys:(NSArray *)keys omitKeys:(NSArray *)omitKeys co
[task resume];
- COUNTLY_LOG(@"Remote Config Request <%p> started:\n[%@] %@", (id)request, request.HTTPMethod, request.URL.absoluteString);
+ CLY_LOG_D(@"Remote Config Request <%p> started:\n[%@] %@", (id)request, request.HTTPMethod, request.URL.absoluteString);
}
- (NSURLRequest *)remoteConfigRequestForKeys:(NSArray *)keys omitKeys:(NSArray *)omitKeys
diff --git a/src/ios/CountlyiOS/CountlyUserDetails.h b/src/ios/CountlyiOS/CountlyUserDetails.h
index 37bf0f2..d1230ab 100644
--- a/src/ios/CountlyiOS/CountlyUserDetails.h
+++ b/src/ios/CountlyiOS/CountlyUserDetails.h
@@ -129,21 +129,53 @@ extern NSString* const kCountlyLocalPicturePath;
#pragma mark -
/**
- * Custom user details property modifier for setting a key-value pair.
+ * Custom user details property modifier for setting a key-value pair where the value is a string.
* @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
* @param key Key for custom property key-value pair
- * @param value Value for custom property key-value pair
+ * @param value String value for custom property key-value pair
*/
- (void)set:(NSString *)key value:(NSString *)value;
+/**
+ * Custom user details property modifier for setting a key-value pair where the value is a number.
+ * @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
+ * @param key Key for custom property key-value pair
+ * @param value Number value for custom property key-value pair
+ */
+- (void)set:(NSString *)key numberValue:(NSNumber *)value;
+
+/**
+ * Custom user details property modifier for setting a key-value pair where the value is a boolean.
+ * @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
+ * @param key Key for custom property key-value pair
+ * @param value Boolean value for custom property key-value pair
+ */
+- (void)set:(NSString *)key boolValue:(BOOL)value;
+
/**
* Custom user details property modifier for setting a key-value pair if not set before.
* @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
* @param key Key for custom property key-value pair
- * @param value Value for custom property key-value pair
+ * @param value String value for custom property key-value pair
*/
- (void)setOnce:(NSString *)key value:(NSString *)value;
+/**
+ * Custom user details property modifier for setting a key-value pair if not set before.
+ * @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
+ * @param key Key for custom property key-value pair
+ * @param value Number value for custom property key-value pair
+ */
+- (void)setOnce:(NSString *)key numberValue:(NSNumber *)value;
+
+/**
+ * Custom user details property modifier for setting a key-value pair if not set before.
+ * @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
+ * @param key Key for custom property key-value pair
+ * @param value Boolean value for custom property key-value pair
+ */
+- (void)setOnce:(NSString *)key boolValue:(BOOL)value;
+
/**
* Custom user details property modifier for unsetting a key-value pair.
* @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
@@ -191,13 +223,29 @@ extern NSString* const kCountlyLocalPicturePath;
- (void)min:(NSString *)key value:(NSNumber *)value;
/**
- * Custom user details property modifier for adding specified value to the array for specified key.
+ * Custom user details property modifier for adding specified string value to the array for specified key.
* @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
* @param key Key for custom property of array type
- * @param value Value to be added to the array
+ * @param value String value to be added to the array
*/
- (void)push:(NSString *)key value:(NSString *)value;
+/**
+ * Custom user details property modifier for adding specified number value to the array for specified key.
+ * @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
+ * @param key Key for custom property of array type
+ * @param value Number value to be added to the array
+ */
+- (void)push:(NSString *)key numberValue:(NSNumber *)value;
+
+/**
+ * Custom user details property modifier for adding specified boolean value to the array for specified key.
+ * @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
+ * @param key Key for custom property of array type
+ * @param value Boolean value to be added to the array
+ */
+- (void)push:(NSString *)key boolValue:(BOOL)value;
+
/**
* Custom user details property modifier for adding specified values to the array for specified key.
* @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
@@ -207,13 +255,29 @@ extern NSString* const kCountlyLocalPicturePath;
- (void)push:(NSString *)key values:(NSArray *)value;
/**
- * Custom user details property modifier for adding specified value to the array for specified key, if it does not exist.
+ * Custom user details property modifier for adding specified string value to the array for specified key, if it does not exist.
* @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
* @param key Key for custom property of array type
- * @param value Value to be added to the array
+ * @param value String value to be added to the array
*/
- (void)pushUnique:(NSString *)key value:(NSString *)value;
+/**
+ * Custom user details property modifier for adding specified number value to the array for specified key, if it does not exist.
+ * @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
+ * @param key Key for custom property of array type
+ * @param value Number value to be added to the array
+ */
+- (void)pushUnique:(NSString *)key numberValue:(NSNumber *)value;
+
+/**
+ * Custom user details property modifier for adding specified boolean value to the array for specified key, if it does not exist.
+ * @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
+ * @param key Key for custom property of array type
+ * @param value Boolean value to be added to the array
+ */
+- (void)pushUnique:(NSString *)key boolValue:(BOOL)value;
+
/**
* Custom user details property modifier for adding specified values to the array for specified key, if they do not exist.
* @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
@@ -223,13 +287,29 @@ extern NSString* const kCountlyLocalPicturePath;
- (void)pushUnique:(NSString *)key values:(NSArray *)value;
/**
- * Custom user details property modifier for removing specified value from the array for specified key.
+ * Custom user details property modifier for removing specified string value from the array for specified key.
* @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
* @param key Key for custom property of array type
- * @param value Value to be removed from the array
+ * @param value String value to be removed from the array
*/
- (void)pull:(NSString *)key value:(NSString *)value;
+/**
+ * Custom user details property modifier for removing specified number value from the array for specified key.
+ * @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
+ * @param key Key for custom property of array type
+ * @param value Number value to be removed from the array
+ */
+- (void)pull:(NSString *)key numberValue:(NSNumber *)value;
+
+/**
+ * Custom user details property modifier for removing specified boolean value from the array for specified key.
+ * @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
+ * @param key Key for custom property of array type
+ * @param value Boolean value to be removed from the array
+ */
+- (void)pull:(NSString *)key boolValue:(BOOL)value;
+
/**
* Custom user details property modifier for removing specified values from the array for specified key.
* @discussion When called, this modifier is added to a non-persistent queue and sent to server only when @c save method is called.
diff --git a/src/ios/CountlyiOS/CountlyUserDetails.m b/src/ios/CountlyiOS/CountlyUserDetails.m
index a134053..fe6d042 100644
--- a/src/ios/CountlyiOS/CountlyUserDetails.m
+++ b/src/ios/CountlyiOS/CountlyUserDetails.m
@@ -102,11 +102,37 @@ - (void)set:(NSString *)key value:(NSString *)value
self.modifications[key] = value.copy;
}
+- (void)set:(NSString *)key numberValue:(NSNumber *)value
+{
+ self.modifications[key] = value.copy;
+}
+
+- (void)set:(NSString *)key boolValue:(BOOL)value
+{
+ self.modifications[key] = @(value);
+}
+
- (void)setOnce:(NSString *)key value:(NSString *)value
{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierSetOnce: value.copy};
}
+- (void)setOnce:(NSString *)key numberValue:(NSNumber *)value
+{
+ if (!value)
+ return;
+
+ self.modifications[key] = @{kCountlyUDKeyModifierSetOnce: value.copy};
+}
+
+- (void)setOnce:(NSString *)key boolValue:(BOOL)value;
+{
+ self.modifications[key] = @{kCountlyUDKeyModifierSetOnce: @(value)};
+}
+
- (void)unSet:(NSString *)key
{
self.modifications[key] = NSNull.null;
@@ -119,51 +145,120 @@ - (void)increment:(NSString *)key
- (void)incrementBy:(NSString *)key value:(NSNumber *)value
{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierIncrement: value};
}
- (void)multiply:(NSString *)key value:(NSNumber *)value
{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierMultiply: value};
}
- (void)max:(NSString *)key value:(NSNumber *)value
{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierMax: value};
}
- (void)min:(NSString *)key value:(NSNumber *)value
{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierMin: value};
}
- (void)push:(NSString *)key value:(NSString *)value
{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierPush: value.copy};
}
+- (void)push:(NSString *)key numberValue:(NSNumber *)value;
+{
+ if (!value)
+ return;
+
+ self.modifications[key] = @{kCountlyUDKeyModifierPush: value.copy};
+}
+
+- (void)push:(NSString *)key boolValue:(BOOL)value
+{
+ self.modifications[key] = @{kCountlyUDKeyModifierPush: @(value)};
+}
+
- (void)push:(NSString *)key values:(NSArray *)value
{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierPush: value.copy};
}
- (void)pushUnique:(NSString *)key value:(NSString *)value
{
+ if (!value)
+ return;
+
+ self.modifications[key] = @{kCountlyUDKeyModifierAddToSet: value.copy};
+}
+
+- (void)pushUnique:(NSString *)key numberValue:(NSNumber *)value
+{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierAddToSet: value.copy};
}
+- (void)pushUnique:(NSString *)key boolValue:(BOOL)value
+{
+ self.modifications[key] = @{kCountlyUDKeyModifierAddToSet: @(value)};
+}
+
- (void)pushUnique:(NSString *)key values:(NSArray *)value
{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierAddToSet: value.copy};
}
- (void)pull:(NSString *)key value:(NSString *)value
{
+ if (!value)
+ return;
+
+ self.modifications[key] = @{kCountlyUDKeyModifierPull: value.copy};
+}
+
+- (void)pull:(NSString *)key numberValue:(NSNumber *)value
+{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierPull: value.copy};
}
+- (void)pull:(NSString *)key boolValue:(BOOL)value
+{
+ self.modifications[key] = @{kCountlyUDKeyModifierPull: @(value)};
+}
+
- (void)pull:(NSString *)key values:(NSArray *)value
{
+ if (!value)
+ return;
+
self.modifications[key] = @{kCountlyUDKeyModifierPull: value.copy};
}
diff --git a/src/ios/CountlyiOS/CountlyViewTracking.m b/src/ios/CountlyiOS/CountlyViewTracking.m
index 33cee4f..af21388 100644
--- a/src/ios/CountlyiOS/CountlyViewTracking.m
+++ b/src/ios/CountlyiOS/CountlyViewTracking.m
@@ -114,7 +114,7 @@ - (void)startView:(NSString *)viewName customSegmentation:(NSDictionary *)custom
[self endView];
- COUNTLY_LOG(@"View tracking started: %@", viewName);
+ CLY_LOG_D(@"View tracking started: %@", viewName);
NSMutableDictionary* segmentation = NSMutableDictionary.new;
segmentation[kCountlyVTKeyName] = viewName;
@@ -152,7 +152,7 @@ - (void)endView
self.accumulatedTime = 0;
[Countly.sharedInstance recordReservedEvent:kCountlyReservedEventView segmentation:segmentation count:1 sum:0 duration:duration timestamp:self.lastViewStartTime];
- COUNTLY_LOG(@"View tracking ended: %@ duration: %.17g", self.lastView, duration);
+ CLY_LOG_D(@"View tracking ended: %@ duration: %.17g", self.lastView, duration);
}
}
@@ -250,6 +250,9 @@ - (NSString*)titleForViewController:(UIViewController *)viewController
if (!title)
title = [viewController.navigationItem.titleView isKindOfClass:UILabel.class] ? ((UILabel *)viewController.navigationItem.titleView).text : nil;
+ if (!title)
+ title = viewController.navigationItem.title;
+
if (!title)
title = NSStringFromClass(viewController.class);
@@ -301,12 +304,15 @@ - (void)Countly_viewDidAppear:(BOOL)animated
for (NSString* exception in CountlyViewTracking.sharedInstance.exceptionViewControllers)
{
- isException = [self.title isEqualToString:exception] ||
+ isException = [viewTitle isEqualToString:exception] ||
[self isKindOfClass:NSClassFromString(exception)] ||
[NSStringFromClass(self.class) isEqualToString:exception];
if (isException)
+ {
+ CLY_LOG_V(@"%@ is an exceptional view, so it will be ignored for view tracking.", viewTitle);
break;
+ }
}
if (!isException)
diff --git a/src/ios/CountlyiOS/Package.swift b/src/ios/CountlyiOS/Package.swift
new file mode 100644
index 0000000..216f05f
--- /dev/null
+++ b/src/ios/CountlyiOS/Package.swift
@@ -0,0 +1,55 @@
+// swift-tools-version:5.3
+
+import PackageDescription
+
+let package = Package(
+
+ name: "Countly",
+
+ platforms:
+ [
+ .iOS(.v8),
+ .macOS(.v10_10),
+ .tvOS(.v9),
+ .watchOS(.v2)
+ ],
+
+ products:
+ [
+ .library(
+ name: "Countly",
+ targets: ["Countly"]),
+ ],
+
+ targets:
+ [
+ .target(
+ name: "Countly",
+ dependencies: [],
+ path: ".",
+
+ exclude:
+ [
+ "Info.plist",
+ "Countly.podspec",
+ "LICENSE.md",
+ "README.md",
+ "countly_dsym_uploader.sh",
+ "CHANGELOG.md"
+ ],
+
+ linkerSettings:
+ [
+ .linkedFramework("Foundation"),
+ .linkedFramework("UIKit", .when(platforms: [.iOS, .tvOS])),
+ .linkedFramework("WatchKit", .when(platforms: [.watchOS])),
+ .linkedFramework("WatchConnectivity", .when(platforms: [.iOS, .watchOS])),
+ .linkedFramework("AppKit", .when(platforms: [.macOS])),
+ .linkedFramework("IOKit", .when(platforms: [.macOS])),
+ .linkedFramework("UserNotifications", .when(platforms: [.iOS, .macOS])),
+ .linkedFramework("CoreLocation"),
+ .linkedFramework("WebKit", .when(platforms: [.iOS])),
+ .linkedFramework("CoreTelephony", .when(platforms: [.iOS])),
+ ]),
+ ]
+)