Skip to content

Commit d265a53

Browse files
authored
Merge pull request #130 from erkanyildiz/master
For 18.08
2 parents 569ec5d + 8a1a7de commit d265a53

16 files changed

+358
-107
lines changed

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,26 @@
1+
## 18.08
2+
- Added feedback widgets support
3+
- Added limit for number of custom crash logs (100 logs)
4+
- Added limit for each custom crash log length (1000 chars)
5+
- Added support for cancelling timed events
6+
- Added support for recording fatal exceptions manually
7+
- Added `userInfo` to crash report custom property
8+
- Added delay before sending change device ID request (server requirement)
9+
- Renamed `isAutoViewTrackingEnabled` as `isAutoViewTrackingActive`
10+
- Fixed Xcode warnings for `askForNotificationPermission` method
11+
- Fixed `UIAlertController` leak in push notification manager
12+
- Fixed `crashSegmentation` availability for manually recorded crashes
13+
- Fixed `openURL:` call thread as main thread
14+
- Updated minimum supported `macOS` version as `10.10`
15+
16+
- Other various improvements
17+
- Discarded separate `UIWindow` for presenting `UIAlertControllers`
18+
- Refactored `buildUUID` and `executableName` as properties
19+
- Refactored custom crash log array and date formatter
20+
- Updated HeaderDocs, inline notes, pragma marks
21+
22+
23+
124
## 18.04
225
- Added consent management for GDPR compliance
326
- Exposed device ID to be used for data export and/or removal requests

Countly.h

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,13 @@ NS_ASSUME_NONNULL_BEGIN
236236
*/
237237
- (void)endEvent:(NSString *)key segmentation:(NSDictionary * _Nullable)segmentation count:(NSUInteger)count sum:(double)sum;
238238

239+
/**
240+
* Cancels a previously started timed event with given key.
241+
* @discussion Trying to cancel an event with already cancelled (or ended or not yet started) key will have no effect.
242+
* @param key Event key
243+
*/
244+
- (void)cancelEvent:(NSString *)key;
245+
239246

240247

241248
#pragma mark - Push Notification
@@ -308,6 +315,7 @@ NS_ASSUME_NONNULL_BEGIN
308315

309316
/**
310317
* @c isGeoLocationEnabled property is deprecated. Please use @c disableLocationInfo method instead.
318+
* @discussion Using this property will have no effect.
311319
*/
312320
@property (nonatomic) BOOL isGeoLocationEnabled DEPRECATED_MSG_ATTRIBUTE("Use 'disableLocationInfo' method instead!");
313321

@@ -328,6 +336,14 @@ NS_ASSUME_NONNULL_BEGIN
328336
*/
329337
- (void)recordHandledException:(NSException *)exception withStackTrace:(NSArray * _Nullable)stackTrace;
330338

339+
/**
340+
* Records an unhandled exception and given stack trace manually.
341+
* @discussion For recording non-native level fatal exceptions, where the app keeps running at native level and can recover.
342+
* @param exception Exception to be reported
343+
* @param stackTrace Stack trace to be reported
344+
*/
345+
- (void)recordUnhandledException:(NSException *)exception withStackTrace:(NSArray * _Nullable)stackTrace;
346+
331347
/**
332348
* Records custom logs to be delivered with crash report.
333349
* @discussion Logs recorded by this method are stored in a non-persistent structure, and delivered to Countly Server only in case of a crash.
@@ -370,7 +386,7 @@ NS_ASSUME_NONNULL_BEGIN
370386
/**
371387
* Records a visited view with given name.
372388
* @discussion Total duration of the view will be calculated on next @c recordView: call.
373-
* @discussion If AutoViewTracking feature is activated on initial configuration, this method does not need to be called manually.
389+
* @discussion If AutoViewTracking feature is enabled on initial configuration, this method does not need to be called manually.
374390
* @param viewName Name of the view visited
375391
*/
376392
- (void)recordView:(NSString *)viewName;
@@ -398,10 +414,17 @@ NS_ASSUME_NONNULL_BEGIN
398414
- (void)removeExceptionForAutoViewTracking:(NSString *)exception;
399415

400416
/**
401-
* Enables or disables AutoViewTracking, if AutoViewTracking feature is activated on initial configuration.
402-
* @discussion If AutoViewTracking feature is not activated on initial configuration, this property has no effect on enabling or disabling it later.
417+
* Temporarily activates or deactivates AutoViewTracking, if AutoViewTracking feature is enabled on initial configuration.
418+
* @discussion If AutoViewTracking feature is not enabled on initial configuration, this property has no effect.
403419
*/
404-
@property (nonatomic) BOOL isAutoViewTrackingEnabled;
420+
@property (nonatomic) BOOL isAutoViewTrackingActive;
421+
422+
/**
423+
* @c isAutoViewTrackingEnabled property is deprecated. Please use @c isAutoViewTrackingActive property instead.
424+
* @discussion Using this property will have no effect.
425+
*/
426+
@property (nonatomic) BOOL isAutoViewTrackingEnabled DEPRECATED_MSG_ATTRIBUTE("Use 'isAutoViewTrackingActive' property instead!");
427+
405428
#endif
406429

407430

@@ -440,6 +463,18 @@ NS_ASSUME_NONNULL_BEGIN
440463
* @param completion A block object to be executed when user gives a star-rating or dismisses dialog without rating
441464
*/
442465
- (void)askForStarRating:(void(^)(NSInteger rating))completion;
466+
467+
/**
468+
* Presents feedback widget with given ID in a WKWebView placed in a UIViewController.
469+
* @discussion First, the availability of the feedback widget will be checked asynchronously.
470+
* @discussion If the feedback widget with given ID is available, it will be modally presented.
471+
* @discussion Otherwise, @c completionHandler will be called with an @c NSError.
472+
* @discussion @c completionHandler will also be called with @c nil when feedback widget is dismissed by user.
473+
* @param widgetID ID of the feedback widget created on Countly Server.
474+
* @param completionHandler A completion handler block to be executed when feedback widget is dismissed by user or there is an error.
475+
*/
476+
- (void)presentFeedbackWidgetWithID:(NSString *)widgetID completionHandler:(void (^)(NSError * error))completionHandler;
477+
443478
#endif
444479

445480
NS_ASSUME_NONNULL_END

Countly.m

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,11 @@ - (void)startWithConfig:(CountlyConfig *)config
117117
[CountlyPushNotifications.sharedInstance startPushNotifications];
118118
}
119119

120+
CountlyCrashReporter.sharedInstance.crashSegmentation = config.crashSegmentation;
121+
CountlyCrashReporter.sharedInstance.crashLogLimit = MAX(1, config.crashLogLimit);
120122
if ([config.features containsObject:CLYCrashReporting])
121123
{
122124
CountlyCrashReporter.sharedInstance.isEnabledOnInitialConfig = YES;
123-
CountlyCrashReporter.sharedInstance.crashSegmentation = config.crashSegmentation;
124125
[CountlyCrashReporter.sharedInstance startCrashReporting];
125126
}
126127
#endif
@@ -471,7 +472,7 @@ - (void)endEvent:(NSString *)key segmentation:(NSDictionary *)segmentation count
471472

472473
if (!event)
473474
{
474-
COUNTLY_LOG(@"Event with key '%@' not started before!", key);
475+
COUNTLY_LOG(@"Event with key '%@' not started yet or cancelled/ended before!", key);
475476
return;
476477
}
477478

@@ -483,20 +484,29 @@ - (void)endEvent:(NSString *)key segmentation:(NSDictionary *)segmentation count
483484
[CountlyPersistency.sharedInstance recordEvent:event];
484485
}
485486

487+
- (void)cancelEvent:(NSString *)key
488+
{
489+
if (!CountlyConsentManager.sharedInstance.consentForEvents)
490+
return;
491+
492+
CountlyEvent *event = [CountlyPersistency.sharedInstance timedEventForKey:key];
493+
494+
if (!event)
495+
{
496+
COUNTLY_LOG(@"Event with key '%@' not started yet or cancelled/ended before!", key);
497+
return;
498+
}
499+
500+
COUNTLY_LOG(@"Event with key '%@' cancelled!", key);
501+
}
486502

487503

488504
#pragma mark - Push Notifications
489505
#if TARGET_OS_IOS
490506

491507
- (void)askForNotificationPermission
492508
{
493-
NSUInteger options = 0;
494-
if (@available(iOS 10.0, *))
495-
options = UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert;
496-
else
497-
options = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
498-
499-
[CountlyPushNotifications.sharedInstance askForNotificationPermissionWithOptions:options completionHandler:nil];
509+
[CountlyPushNotifications.sharedInstance askForNotificationPermissionWithOptions:0 completionHandler:nil];
500510
}
501511

502512
- (void)askForNotificationPermissionWithOptions:(UNAuthorizationOptions)options completionHandler:(void (^)(BOOL granted, NSError * error))completionHandler;
@@ -541,12 +551,17 @@ - (void)disableLocationInfo
541551
#if TARGET_OS_IOS
542552
- (void)recordHandledException:(NSException *)exception
543553
{
544-
[CountlyCrashReporter.sharedInstance recordHandledException:exception withStackTrace:nil];
554+
[CountlyCrashReporter.sharedInstance recordException:exception withStackTrace:nil isFatal:NO];
545555
}
546556

547557
- (void)recordHandledException:(NSException *)exception withStackTrace:(NSArray *)stackTrace
548558
{
549-
[CountlyCrashReporter.sharedInstance recordHandledException:exception withStackTrace:stackTrace];
559+
[CountlyCrashReporter.sharedInstance recordException:exception withStackTrace:stackTrace isFatal:NO];
560+
}
561+
562+
- (void)recordUnhandledException:(NSException *)exception withStackTrace:(NSArray * _Nullable)stackTrace
563+
{
564+
[CountlyCrashReporter.sharedInstance recordException:exception withStackTrace:stackTrace isFatal:YES];
550565
}
551566

552567
- (void)recordCrashLog:(NSString *)log
@@ -600,14 +615,14 @@ - (void)removeExceptionForAutoViewTracking:(NSString *)exception
600615
[CountlyViewTracking.sharedInstance removeExceptionForAutoViewTracking:exception.copy];
601616
}
602617

603-
- (void)setIsAutoViewTrackingEnabled:(BOOL)isAutoViewTrackingEnabled
618+
- (void)setIsAutoViewTrackingActive:(BOOL)isAutoViewTrackingActive
604619
{
605-
CountlyViewTracking.sharedInstance.isAutoViewTrackingEnabled = isAutoViewTrackingEnabled;
620+
CountlyViewTracking.sharedInstance.isAutoViewTrackingActive = isAutoViewTrackingActive;
606621
}
607622

608-
- (BOOL)isAutoViewTrackingEnabled
623+
- (BOOL)isAutoViewTrackingActive
609624
{
610-
return CountlyViewTracking.sharedInstance.isAutoViewTrackingEnabled;
625+
return CountlyViewTracking.sharedInstance.isAutoViewTrackingActive;
611626
}
612627
#endif
613628

@@ -639,6 +654,12 @@ - (void)askForStarRating:(void(^)(NSInteger rating))completion
639654
{
640655
[CountlyStarRating.sharedInstance showDialog:completion];
641656
}
657+
658+
- (void)presentFeedbackWidgetWithID:(NSString *)widgetID completionHandler:(void (^)(NSError * error))completionHandler
659+
{
660+
[CountlyStarRating.sharedInstance checkFeedbackWidgetWithID:widgetID completionHandler:completionHandler];
661+
}
662+
642663
#endif
643664

644665
@end

Countly.podspec

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = 'Countly'
3-
s.version = '18.04'
3+
s.version = '18.08'
44
s.license = {
55
:type => 'COMMUNITY',
66
:text => <<-LICENSE
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
3737
s.public_header_files = 'Countly.h', 'CountlyUserDetails.h', 'CountlyConfig.h'
3838
s.requires_arc = true
3939
s.ios.deployment_target = '8.0'
40-
s.osx.deployment_target = '10.9'
40+
s.osx.deployment_target = '10.10'
4141
s.watchos.deployment_target = '2.0'
4242
s.tvos.deployment_target = '9.0'
4343

CountlyCommon.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@
5858
extern NSString* const kCountlySDKVersion;
5959
extern NSString* const kCountlySDKName;
6060

61+
extern NSString* const kCountlyErrorDomain;
62+
63+
NS_ERROR_ENUM(kCountlyErrorDomain)
64+
{
65+
CLYErrorFeedbackWidgetNotAvailable = 10001,
66+
CLYErrorFeedbackWidgetNotTargetedForDevice = 10002,
67+
};
68+
6169
@interface CountlyCommon : NSObject
6270

6371
@property (nonatomic) BOOL hasStarted;

CountlyCommon.m

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@ @interface CountlyCommon ()
1818
#endif
1919
@end
2020

21-
NSString* const kCountlySDKVersion = @"18.04";
21+
NSString* const kCountlySDKVersion = @"18.08";
2222
NSString* const kCountlySDKName = @"objc-native-ios";
2323

2424
NSString* const kCountlyParentDeviceIDTransferKey = @"kCountlyParentDeviceIDTransferKey";
2525
NSString* const kCountlyAttributionIDFAKey = @"idfa";
2626

27+
NSString* const kCountlyErrorDomain = @"ly.count.ErrorDomain";
28+
2729
@implementation CountlyCommon
2830

2931
+ (instancetype)sharedInstance
@@ -229,25 +231,6 @@ - (UIViewController *)topViewController
229231
#if TARGET_OS_IOS
230232
@implementation CLYInternalViewController : UIViewController
231233

232-
//NOTE: Use the same status bar preferences as the currently displayed view controller, when a Countly triggered alert is displayed in a separate window
233-
- (UIStatusBarStyle)preferredStatusBarStyle
234-
{
235-
UIViewController* topVC = [CountlyCommon.sharedInstance topViewController];
236-
if (topVC == self)
237-
return UIStatusBarStyleDefault;
238-
239-
return [topVC preferredStatusBarStyle];
240-
}
241-
242-
- (BOOL)prefersStatusBarHidden
243-
{
244-
UIViewController* topVC = [CountlyCommon.sharedInstance topViewController];
245-
if (topVC == self)
246-
return NO;
247-
248-
return [topVC prefersStatusBarHidden];
249-
}
250-
251234
@end
252235

253236

CountlyConfig.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,9 @@ extern NSString* const CLYConsentAppleWatch;
174174
@property (nonatomic) NSUInteger eventSendThreshold;
175175

176176
/**
177-
* Stored requests limit is used for limiting the number of request to be stored on the device, in case of a Countly Server connection problem.
177+
* Stored requests limit is used for limiting the number of request to be stored on the device, in case Countly Server is not reachable.
178178
* @discussion In case Countly Server is down or unreachable for a very long time, queued request may reach excessive numbers, and this may cause problems with requests being sent to Countly Server and being stored on the device. To prevent this, SDK will only store requests up to @c storedRequestsLimit.
179-
* @discussion If number of stored requests reach @c storedRequestsLimit, SDK will start to drop oldest request while inserting the newest one instead.
179+
* @discussion If number of stored requests reaches @c storedRequestsLimit, SDK will start to drop oldest request while appending the newest one.
180180
* @discussion If not set, it will be 1000 by default.
181181
*/
182182
@property (nonatomic) NSUInteger storedRequestsLimit;
@@ -214,6 +214,13 @@ extern NSString* const CLYConsentAppleWatch;
214214
*/
215215
@property (nonatomic, copy) NSDictionary* crashSegmentation;
216216

217+
/**
218+
* Crash log limit is used for limiting the number of crash logs to be stored on the device.
219+
* @discussion If number of stored crash logs reaches @c crashLogLimit, SDK will start to drop oldest crash log while appending the newest one.
220+
* @discussion If not set, it will be 100 by default.
221+
*/
222+
@property (nonatomic) NSUInteger crashLogLimit;
223+
217224
#pragma mark -
218225

219226
/**

CountlyConfig.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ - (instancetype)init
4343
self.eventSendThreshold = 10;
4444
#endif
4545
self.storedRequestsLimit = 1000;
46+
self.crashLogLimit = 100;
4647

4748
self.location = kCLLocationCoordinate2DInvalid;
4849
}

CountlyConnectionManager.m

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ @interface CountlyConnectionManager ()
1111
NSTimeInterval unsentSessionLength;
1212
NSTimeInterval lastSessionStartTime;
1313
BOOL isCrashing;
14+
BOOL isDelayingDeviceIDChange;
15+
BOOL hasAlreadyDelayedDeviceIDChange;
1416
}
1517
@end
1618

@@ -78,7 +80,7 @@ - (instancetype)init
7880

7981
- (void)proceedOnQueue
8082
{
81-
if (self.connection || isCrashing)
83+
if (self.connection || isCrashing || isDelayingDeviceIDChange)
8284
return;
8385

8486
if (self.customHeaderFieldName && !self.customHeaderFieldValue)
@@ -100,6 +102,20 @@ - (void)proceedOnQueue
100102
return;
101103
}
102104

105+
if ([firstItemInQueue containsString:[NSString stringWithFormat:@"&%@=", kCountlyQSKeyDeviceIDOld]] && !hasAlreadyDelayedDeviceIDChange)
106+
{
107+
COUNTLY_LOG(@"Server needs changing device ID request to be delayed 10 sec");
108+
109+
isDelayingDeviceIDChange = YES;
110+
hasAlreadyDelayedDeviceIDChange = YES;
111+
112+
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(endDelayingDeviceIDChange) object:nil];
113+
[self performSelector:@selector(endDelayingDeviceIDChange) withObject:nil afterDelay:10];
114+
return;
115+
}
116+
117+
hasAlreadyDelayedDeviceIDChange = NO;
118+
103119
[CountlyCommon.sharedInstance startBackgroundTask];
104120

105121
NSString* queryString = firstItemInQueue;
@@ -534,6 +550,12 @@ - (BOOL)isRequestSuccessful:(NSURLResponse *)response
534550
return (code >= 200 && code < 300);
535551
}
536552

553+
- (void)endDelayingDeviceIDChange
554+
{
555+
isDelayingDeviceIDChange = NO;
556+
[self proceedOnQueue];
557+
}
558+
537559
#pragma mark ---
538560

539561
- (NSURLSession *)URLSession

CountlyCrashReporter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
#if TARGET_OS_IOS
1111
@property (nonatomic) BOOL isEnabledOnInitialConfig;
1212
@property (nonatomic) NSDictionary* crashSegmentation;
13+
@property (nonatomic) NSUInteger crashLogLimit;
1314

1415
+ (instancetype)sharedInstance;
1516
- (void)startCrashReporting;
1617
- (void)stopCrashReporting;
17-
- (void)recordHandledException:(NSException *)exception withStackTrace:(NSArray *)stackTrace;
18+
- (void)recordException:(NSException *)exception withStackTrace:(NSArray *)stackTrace isFatal:(BOOL)isFatal;
1819
- (void)log:(NSString *)log;
1920
#endif
2021
@end

0 commit comments

Comments
 (0)