From 3f09aec42935b0406ea94b465e7f0764d794f851 Mon Sep 17 00:00:00 2001 From: NachoSoto Date: Wed, 14 May 2014 00:35:19 +0000 Subject: [PATCH 01/16] Added +setShowPreliminaryMessage: to optionally display a preliminary message before asking to rate --- Appirater.h | 20 +++- Appirater.m | 223 +++++++++++++++++++++++++++++--------------- AppiraterDelegate.h | 4 + 3 files changed, 173 insertions(+), 74 deletions(-) diff --git a/Appirater.h b/Appirater.h index b0d5f582..22b42ba8 100644 --- a/Appirater.h +++ b/Appirater.h @@ -57,7 +57,20 @@ extern NSString *const kAppiraterReminderRequestDate; #define APPIRATER_APP_NAME APPIRATER_LOCALIZED_APP_NAME ? APPIRATER_LOCALIZED_APP_NAME : [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"] /*! - This is the message your users will see once they've passed the day+launches + This is first message your users will see once they've passed the day+launches + threshold. + */ +#define APPIRATER_LOCALIZED_PRELIMINARY_MESSAGE_TITLE NSLocalizedStringFromTableInBundle(@"%@", @"AppiraterLocalizable", [Appirater bundle], nil) +#define APPIRATER_PRELIMINARY_MESSAGE_TITLE [NSString stringWithFormat:APPIRATER_LOCALIZED_PRELIMINARY_MESSAGE_TITLE, APPIRATER_APP_NAME] + +#define APPIRATER_LOCALIZED_PRELIMINARY_MESSAGE NSLocalizedStringFromTableInBundle(@"Are you enjoying %@?", @"AppiraterLocalizable", [Appirater bundle], nil) +#define APPIRATER_PRELIMINARY_MESSAGE [NSString stringWithFormat:APPIRATER_LOCALIZED_PRELIMINARY_MESSAGE, APPIRATER_APP_NAME] + +#define APPIRATER_PRELIMINARY_MESSAGE_YES_BUTTON NSLocalizedStringFromTableInBundle(@"Yes", @"AppiraterLocalizable", [Appirater bundle], nil) +#define APPIRATER_PRELIMINARY_MESSAGE_NO_BUTTON NSLocalizedStringFromTableInBundle(@"No", @"AppiraterLocalizable", [Appirater bundle], nil) + +/*! + This is the message your users will see once they've seen the first message threshold. */ #define APPIRATER_LOCALIZED_MESSAGE NSLocalizedStringFromTableInBundle(@"If you enjoy using %@, would you mind taking a moment to rate it? It won't take more than a minute. Thanks for your support!", @"AppiraterLocalizable", [Appirater bundle], nil) @@ -191,6 +204,11 @@ extern NSString *const kAppiraterReminderRequestDate; */ + (void) setAppId:(NSString*)appId; +/*! + Users will see a preliminary message before asked to rate the app. + */ ++ (void) setShowPreliminaryMessage:(BOOL)showPreliminaryMessage; + /*! Users will need to have the same version of your app installed for this many days before they will be prompted to rate it. diff --git a/Appirater.m b/Appirater.m index bceaf2ad..2b1b664a 100644 --- a/Appirater.m +++ b/Appirater.m @@ -53,7 +53,21 @@ NSString *templateReviewURL = @"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=APP_ID"; NSString *templateReviewURLiOS7 = @"itms-apps://itunes.apple.com/app/idAPP_ID"; +static const NSInteger AlertButtonIndexInvalid = -1; + +typedef NS_ENUM(NSInteger, PreliminaryAlertButtonIndex) { + PreliminaryAlertButtonNo = 0, + PreliminaryAlertButtonYes +}; + +typedef NS_ENUM(NSInteger, RateAlertButtonIndex) { + RateAlertButtonIndexRateNow = 0, + RateAlertButtonIndexDontRate, + RateAlertButtonIndexRateLater +}; + static NSString *_appId; +static BOOL _showPreliminaryMessage = NO; static double _daysUntilPrompt = 30; static NSInteger _usesUntilPrompt = 20; static NSInteger _significantEventsUntilPrompt = -1; @@ -64,21 +78,18 @@ #else __weak static id _delegate; #endif -static BOOL _usesAnimation = TRUE; +static BOOL _usesAnimation = YES; static UIStatusBarStyle _statusBarStyle; -static BOOL _modalOpen = false; +static BOOL _modalOpen = NO; static BOOL _alwaysUseMainBundle = NO; -@interface Appirater () -- (BOOL)connectedToNetwork; -+ (Appirater*)sharedInstance; -- (void)showPromptWithChecks:(BOOL)withChecks - displayRateLaterButton:(BOOL)displayRateLaterButton; -- (void)showRatingAlert:(BOOL)displayRateLaterButton; -- (void)showRatingAlert; -- (BOOL)ratingConditionsHaveBeenMet; -- (void)incrementUseCount; -- (void)hideRatingAlert; +static const NSInteger kPreliminaryAlertViewTag = 1000; +static const NSInteger kRateAlertViewTag = 1001; + +@interface Appirater () { + BOOL _shouldShowRateLaterButton; +} + @end @implementation Appirater @@ -89,6 +100,10 @@ + (void) setAppId:(NSString *)appId { _appId = appId; } ++ (void) setShowPreliminaryMessage:(BOOL)showPreliminaryMessage { + _showPreliminaryMessage = showPreliminaryMessage; +} + + (void) setDaysUntilPrompt:(double)value { _daysUntilPrompt = value; } @@ -180,7 +195,9 @@ - (BOOL)connectedToNetwork { if (!didRetrieveFlags) { - NSLog(@"Error. Could not recover network reachability flags"); + if (_debug) { + NSLog(@"Error. Could not recover network reachability flags"); + } return NO; } @@ -212,33 +229,61 @@ + (Appirater*)sharedInstance { } - (void)showRatingAlert:(BOOL)displayRateLaterButton { - UIAlertView *alertView = nil; - if (displayRateLaterButton) { - alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE - message:APPIRATER_MESSAGE - delegate:self - cancelButtonTitle:APPIRATER_CANCEL_BUTTON - otherButtonTitles:APPIRATER_RATE_BUTTON, APPIRATER_RATE_LATER, nil]; - } else { - alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE - message:APPIRATER_MESSAGE - delegate:self - cancelButtonTitle:APPIRATER_CANCEL_BUTTON - otherButtonTitles:APPIRATER_RATE_BUTTON, nil]; - } + if (_showPreliminaryMessage) { + _shouldShowRateLaterButton = displayRateLaterButton; + [self reallyShowPreliminaryAlert]; + } else { + [self reallyShowRatingAlert:displayRateLaterButton]; + } +} +- (void)showRatingAlert +{ + [self showRatingAlert:YES]; +} + +- (void)reallyShowPreliminaryAlert { + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_PRELIMINARY_MESSAGE_TITLE + message:APPIRATER_PRELIMINARY_MESSAGE + delegate:self + cancelButtonTitle:APPIRATER_PRELIMINARY_MESSAGE_NO_BUTTON + otherButtonTitles:APPIRATER_PRELIMINARY_MESSAGE_YES_BUTTON, nil]; + alertView.tag = kPreliminaryAlertViewTag; + self.ratingAlert = alertView; [alertView show]; - + id delegate = _delegate; - if (delegate && [delegate respondsToSelector:@selector(appiraterDidDisplayAlert:)]) { - [delegate appiraterDidDisplayAlert:self]; + if (delegate && [delegate respondsToSelector:@selector(appiraterDidDisplayPreliminaryAlert:)]) { + [delegate appiraterDidDisplayPreliminaryAlert:self]; } } -- (void)showRatingAlert -{ - [self showRatingAlert:true]; +- (void)reallyShowRatingAlert:(BOOL)displayRateLaterButton { + UIAlertView *alertView = nil; + if (displayRateLaterButton) { + alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE + message:APPIRATER_MESSAGE + delegate:self + cancelButtonTitle:APPIRATER_CANCEL_BUTTON + otherButtonTitles:APPIRATER_RATE_BUTTON, APPIRATER_RATE_LATER, nil]; + } else { + alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE + message:APPIRATER_MESSAGE + delegate:self + cancelButtonTitle:APPIRATER_CANCEL_BUTTON + otherButtonTitles:APPIRATER_RATE_BUTTON, nil]; + } + + alertView.tag = kRateAlertViewTag; + + self.ratingAlert = alertView; + [alertView show]; + + id delegate = _delegate; + if (delegate && [delegate respondsToSelector:@selector(appiraterDidDisplayAlert:)]) { + [delegate appiraterDidDisplayAlert:self]; + } } - (BOOL)ratingConditionsHaveBeenMet { @@ -428,7 +473,7 @@ - (void)hideRatingAlert { if (self.ratingAlert.visible) { if (_debug) NSLog(@"APPIRATER Hiding Alert"); - [self.ratingAlert dismissWithClickedButtonIndex:-1 animated:NO]; + [self.ratingAlert dismissWithClickedButtonIndex:AlertButtonIndexInvalid animated:NO]; } } @@ -457,18 +502,18 @@ + (void)showPrompt { } + (void)tryToShowPrompt { - [[Appirater sharedInstance] showPromptWithChecks:true - displayRateLaterButton:true]; + [[Appirater sharedInstance] showPromptWithChecks:YES + displayRateLaterButton:YES]; } + (void)forceShowPrompt:(BOOL)displayRateLaterButton { - [[Appirater sharedInstance] showPromptWithChecks:false + [[Appirater sharedInstance] showPromptWithChecks:NO displayRateLaterButton:displayRateLaterButton]; } - (void)showPromptWithChecks:(BOOL)withChecks displayRateLaterButton:(BOOL)displayRateLaterButton { - bool showPrompt = true; + BOOL showPrompt = NO; if (withChecks) { showPrompt = ([self connectedToNetwork] && ![self userHasDeclinedToRate] @@ -526,7 +571,7 @@ + (void)rateApp { if (![Appirater sharedInstance].openInAppStore && NSStringFromClass([SKStoreProductViewController class]) != nil) { SKStoreProductViewController *storeViewController = [[SKStoreProductViewController alloc] init]; - NSNumber *appId = [NSNumber numberWithInteger:_appId.integerValue]; + NSNumber *appId = @(_appId.integerValue); [storeViewController loadProductWithParameters:@{SKStoreProductParameterITunesItemIdentifier:appId} completionBlock:nil]; storeViewController.delegate = self.sharedInstance; @@ -562,41 +607,73 @@ + (void)rateApp { } - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { - NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + id delegate = _delegate; - - switch (buttonIndex) { - case 0: - { - // they don't want to rate it - [userDefaults setBool:YES forKey:kAppiraterDeclinedToRate]; - [userDefaults synchronize]; - if(delegate && [delegate respondsToSelector:@selector(appiraterDidDeclineToRate:)]){ - [delegate appiraterDidDeclineToRate:self]; - } - break; - } - case 1: - { - // they want to rate it - [Appirater rateApp]; - if(delegate&& [delegate respondsToSelector:@selector(appiraterDidOptToRate:)]){ - [delegate appiraterDidOptToRate:self]; - } - break; - } - case 2: - // remind them later - [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterReminderRequestDate]; - [userDefaults synchronize]; - if(delegate && [delegate respondsToSelector:@selector(appiraterDidOptToRemindLater:)]){ - [delegate appiraterDidOptToRemindLater:self]; - } - break; - default: - break; - } + + switch (alertView.tag) { + case kPreliminaryAlertViewTag: + { + switch (buttonIndex) { + case PreliminaryAlertButtonNo: + [self didDeclineToRate]; + + if ([delegate respondsToSelector:@selector(appiraterDidDeclinePreliminaryAlert:)]) { + [delegate appiraterDidDeclinePreliminaryAlert:self]; + } + + break; + case PreliminaryAlertButtonYes: + [self reallyShowRatingAlert:_shouldShowRateLaterButton]; + + if ([delegate respondsToSelector:@selector(appiraterDidAcceptPreliminaryAlert:)]) { + [delegate appiraterDidAcceptPreliminaryAlert:self]; + } + + break; + } + } + break; + case kRateAlertViewTag: + { + switch (buttonIndex) { + case RateAlertButtonIndexDontRate: + { + [self didDeclineToRate]; + break; + } + case RateAlertButtonIndexRateNow: + { + [Appirater rateApp]; + if(delegate&& [delegate respondsToSelector:@selector(appiraterDidOptToRate:)]){ + [delegate appiraterDidOptToRate:self]; + } + break; + } + case RateAlertButtonIndexRateLater: + [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterReminderRequestDate]; + [userDefaults synchronize]; + if(delegate && [delegate respondsToSelector:@selector(appiraterDidOptToRemindLater:)]){ + [delegate appiraterDidOptToRemindLater:self]; + } + break; + default: + break; + } + } + default: + break; + } +} + +- (void)didDeclineToRate { + NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + + [userDefaults setBool:YES forKey:kAppiraterDeclinedToRate]; + [userDefaults synchronize]; + if(_delegate && [_delegate respondsToSelector:@selector(appiraterDidDeclineToRate:)]){ + [_delegate appiraterDidDeclineToRate:self]; + } } //Delegate call from the StoreKit view. diff --git a/AppiraterDelegate.h b/AppiraterDelegate.h index d7722d39..b5a7d7e7 100644 --- a/AppiraterDelegate.h +++ b/AppiraterDelegate.h @@ -13,6 +13,10 @@ @protocol AppiraterDelegate @optional +-(void)appiraterDidDisplayPreliminaryAlert:(Appirater *)appirater; +-(void)appiraterDidDeclinePreliminaryAlert:(Appirater *)appirater; +-(void)appiraterDidAcceptPreliminaryAlert:(Appirater *)appirater; + -(void)appiraterDidDisplayAlert:(Appirater *)appirater; -(void)appiraterDidDeclineToRate:(Appirater *)appirater; -(void)appiraterDidOptToRate:(Appirater *)appirater; From c7d50e08fa455be61634f02f9fda2f517a0d4d99 Mon Sep 17 00:00:00 2001 From: NachoSoto Date: Mon, 19 May 2014 19:21:59 +0000 Subject: [PATCH 02/16] Fixed showPromptWithChecks:displayRateLaterButton: --- Appirater.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Appirater.m b/Appirater.m index 2b1b664a..5ca1d357 100644 --- a/Appirater.m +++ b/Appirater.m @@ -513,7 +513,7 @@ + (void)forceShowPrompt:(BOOL)displayRateLaterButton { - (void)showPromptWithChecks:(BOOL)withChecks displayRateLaterButton:(BOOL)displayRateLaterButton { - BOOL showPrompt = NO; + BOOL showPrompt = YES; if (withChecks) { showPrompt = ([self connectedToNetwork] && ![self userHasDeclinedToRate] From c8df4708485f19c9ba318b7c3b10123eb261bffc Mon Sep 17 00:00:00 2001 From: NachoSoto Date: Fri, 23 May 2014 18:49:41 +0000 Subject: [PATCH 03/16] Fixed RateAlertButtonIndex --- Appirater.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Appirater.m b/Appirater.m index 5ca1d357..6adf3a60 100644 --- a/Appirater.m +++ b/Appirater.m @@ -61,8 +61,8 @@ typedef NS_ENUM(NSInteger, PreliminaryAlertButtonIndex) { }; typedef NS_ENUM(NSInteger, RateAlertButtonIndex) { - RateAlertButtonIndexRateNow = 0, - RateAlertButtonIndexDontRate, + RateAlertButtonIndexDontRate = 0, + RateAlertButtonIndexRateNow, RateAlertButtonIndexRateLater }; From 24d6e63f582112b7786810148b06e361e08ae925 Mon Sep 17 00:00:00 2001 From: Jacob Eiting Date: Thu, 26 Feb 2015 12:17:11 -0800 Subject: [PATCH 04/16] Remove deprecated annotation. --- Appirater.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Appirater.h b/Appirater.h index 22b42ba8..afd37f09 100644 --- a/Appirater.h +++ b/Appirater.h @@ -299,7 +299,7 @@ extern NSString *const kAppiraterReminderRequestDate; Calls [Appirater appLaunched:YES]. See appLaunched: for details of functionality. */ -+ (void)appLaunched __attribute__((deprecated)); ++ (void)appLaunched; /*! DEPRECATED: While still functional, it's better to use @@ -307,6 +307,6 @@ extern NSString *const kAppiraterReminderRequestDate; Calls [Appirater tryToShowPrompt]. See tryToShowPrompt for details of functionality. */ -+ (void)showPrompt __attribute__((deprecated)); ++ (void)showPrompt; @end From 7d69d09cbb3ac851c936bb87ac961df7c184e24c Mon Sep 17 00:00:00 2001 From: Jacob Eiting Date: Thu, 26 Feb 2015 14:32:53 -0800 Subject: [PATCH 05/16] Fix implicit cast. --- Appirater.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Appirater.m b/Appirater.m index 6adf3a60..00bb5bf3 100644 --- a/Appirater.m +++ b/Appirater.m @@ -190,7 +190,7 @@ - (BOOL)connectedToNetwork { SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); SCNetworkReachabilityFlags flags; - BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags); + BOOL didRetrieveFlags = (BOOL)SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags); CFRelease(defaultRouteReachability); if (!didRetrieveFlags) From b88acd5a31f40d5524016ab57a0556fafe13db93 Mon Sep 17 00:00:00 2001 From: Jacob Eiting Date: Tue, 31 Mar 2015 10:22:08 -0700 Subject: [PATCH 06/16] Revert changes that broke the ratng modal. --- Appirater.m | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Appirater.m b/Appirater.m index 00bb5bf3..3d3dfaaf 100644 --- a/Appirater.m +++ b/Appirater.m @@ -46,7 +46,7 @@ NSString *const kAppiraterUseCount = @"kAppiraterUseCount"; NSString *const kAppiraterSignificantEventCount = @"kAppiraterSignificantEventCount"; NSString *const kAppiraterCurrentVersion = @"kAppiraterCurrentVersion"; -NSString *const kAppiraterRatedCurrentVersion = @"kAppiraterRatedCurrentVersion"; +NSString *const kAppiraterRated = @"kAppiraterRated"; NSString *const kAppiraterDeclinedToRate = @"kAppiraterDeclinedToRate"; NSString *const kAppiraterReminderRequestDate = @"kAppiraterReminderRequestDate"; @@ -313,7 +313,7 @@ - (BOOL)ratingConditionsHaveBeenMet { return NO; // has the user already rated the app? - if ([self userHasRatedCurrentVersion]) + if ([self userHasRatedApp]) return NO; // if the user wanted to be reminded later, has enough time passed? @@ -366,7 +366,7 @@ - (void)incrementUseCount { [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterFirstUseDate]; [userDefaults setInteger:1 forKey:kAppiraterUseCount]; [userDefaults setInteger:0 forKey:kAppiraterSignificantEventCount]; - [userDefaults setBool:NO forKey:kAppiraterRatedCurrentVersion]; + [userDefaults setBool:NO forKey:kAppiraterRated]; [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; } @@ -414,7 +414,7 @@ - (void)incrementSignificantEventCount { [userDefaults setDouble:0 forKey:kAppiraterFirstUseDate]; [userDefaults setInteger:0 forKey:kAppiraterUseCount]; [userDefaults setInteger:1 forKey:kAppiraterSignificantEventCount]; - [userDefaults setBool:NO forKey:kAppiraterRatedCurrentVersion]; + [userDefaults setBool:NO forKey:kAppiraterRated]; [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; } @@ -454,8 +454,8 @@ - (BOOL)userHasDeclinedToRate { return [[NSUserDefaults standardUserDefaults] boolForKey:kAppiraterDeclinedToRate]; } -- (BOOL)userHasRatedCurrentVersion { - return [[NSUserDefaults standardUserDefaults] boolForKey:kAppiraterRatedCurrentVersion]; +- (BOOL)userHasRatedApp { + return [[NSUserDefaults standardUserDefaults] boolForKey:kAppiraterRated]; } + (void)appLaunched { @@ -517,7 +517,8 @@ - (void)showPromptWithChecks:(BOOL)withChecks if (withChecks) { showPrompt = ([self connectedToNetwork] && ![self userHasDeclinedToRate] - && ![self userHasRatedCurrentVersion]); + && ![self userHasRatedApp] + && [self ratingConditionsHaveBeenMet]); } if (showPrompt) { [self showRatingAlert:displayRateLaterButton]; @@ -564,7 +565,7 @@ + (UIViewController *) topMostViewController: (UIViewController *) controller { + (void)rateApp { NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; - [userDefaults setBool:YES forKey:kAppiraterRatedCurrentVersion]; + [userDefaults setBool:YES forKey:kAppiraterRated]; [userDefaults synchronize]; //Use the in-app StoreKit view if available (iOS 6) and imported. This works in the simulator. From afa168accf9773f1f5535f70589e1f70a168d8ef Mon Sep 17 00:00:00 2001 From: Jacob Eiting Date: Tue, 31 Mar 2015 10:23:24 -0700 Subject: [PATCH 07/16] Formatting. --- Appirater.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Appirater.m b/Appirater.m index 3d3dfaaf..8c5667df 100644 --- a/Appirater.m +++ b/Appirater.m @@ -515,11 +515,11 @@ - (void)showPromptWithChecks:(BOOL)withChecks displayRateLaterButton:(BOOL)displayRateLaterButton { BOOL showPrompt = YES; if (withChecks) { - showPrompt = ([self connectedToNetwork] - && ![self userHasDeclinedToRate] - && ![self userHasRatedApp] - && [self ratingConditionsHaveBeenMet]); - } + showPrompt = ([self connectedToNetwork] + && ![self userHasDeclinedToRate] + && ![self userHasRatedApp] + && [self ratingConditionsHaveBeenMet]); + } if (showPrompt) { [self showRatingAlert:displayRateLaterButton]; } From 5647253516c731db721093f42f81e6fb83e5551f Mon Sep 17 00:00:00 2001 From: Jacob Eiting Date: Tue, 8 Sep 2015 11:18:10 -0700 Subject: [PATCH 08/16] Don't reset values on upgrade. --- Appirater.m | 97 ++++++++++++++++++++++------------------------------- 1 file changed, 41 insertions(+), 56 deletions(-) diff --git a/Appirater.m b/Appirater.m index 8c5667df..f38ce26f 100644 --- a/Appirater.m +++ b/Appirater.m @@ -337,39 +337,31 @@ - (void)incrementUseCount { { trackingVersion = version; [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; + [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterFirstUseDate]; + [userDefaults setInteger:0 forKey:kAppiraterUseCount]; + [userDefaults setInteger:0 forKey:kAppiraterSignificantEventCount]; + [userDefaults setBool:NO forKey:kAppiraterRated]; + [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; + [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; } if (_debug) NSLog(@"APPIRATER Tracking version: %@", trackingVersion); - if ([trackingVersion isEqualToString:version]) - { - // check if the first use date has been set. if not, set it. - NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterFirstUseDate]; - if (timeInterval == 0) - { - timeInterval = [[NSDate date] timeIntervalSince1970]; - [userDefaults setDouble:timeInterval forKey:kAppiraterFirstUseDate]; - } - - // increment the use count - NSInteger useCount = [userDefaults integerForKey:kAppiraterUseCount]; - useCount++; - [userDefaults setInteger:useCount forKey:kAppiraterUseCount]; - if (_debug) - NSLog(@"APPIRATER Use count: %@", @(useCount)); - } - else - { - // it's a new version of the app, so restart tracking - [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; - [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterFirstUseDate]; - [userDefaults setInteger:1 forKey:kAppiraterUseCount]; - [userDefaults setInteger:0 forKey:kAppiraterSignificantEventCount]; - [userDefaults setBool:NO forKey:kAppiraterRated]; - [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; - [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; - } + // check if the first use date has been set. if not, set it. + NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterFirstUseDate]; + if (timeInterval == 0) + { + timeInterval = [[NSDate date] timeIntervalSince1970]; + [userDefaults setDouble:timeInterval forKey:kAppiraterFirstUseDate]; + } + + // increment the use count + NSInteger useCount = [userDefaults integerForKey:kAppiraterUseCount]; + useCount++; + [userDefaults setInteger:useCount forKey:kAppiraterUseCount]; + if (_debug) + NSLog(@"APPIRATER Use count: %@", @(useCount)); [userDefaults synchronize]; } @@ -385,39 +377,32 @@ - (void)incrementSignificantEventCount { { trackingVersion = version; [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; + [userDefaults setDouble:0 forKey:kAppiraterFirstUseDate]; + [userDefaults setInteger:0 forKey:kAppiraterUseCount]; + [userDefaults setInteger:0 forKey:kAppiraterSignificantEventCount]; + [userDefaults setBool:NO forKey:kAppiraterRated]; + [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; + [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; } if (_debug) NSLog(@"APPIRATER Tracking version: %@", trackingVersion); - if ([trackingVersion isEqualToString:version]) - { - // check if the first use date has been set. if not, set it. - NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterFirstUseDate]; - if (timeInterval == 0) - { - timeInterval = [[NSDate date] timeIntervalSince1970]; - [userDefaults setDouble:timeInterval forKey:kAppiraterFirstUseDate]; - } - - // increment the significant event count - NSInteger sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount]; - sigEventCount++; - [userDefaults setInteger:sigEventCount forKey:kAppiraterSignificantEventCount]; - if (_debug) - NSLog(@"APPIRATER Significant event count: %@", @(sigEventCount)); - } - else - { - // it's a new version of the app, so restart tracking - [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; - [userDefaults setDouble:0 forKey:kAppiraterFirstUseDate]; - [userDefaults setInteger:0 forKey:kAppiraterUseCount]; - [userDefaults setInteger:1 forKey:kAppiraterSignificantEventCount]; - [userDefaults setBool:NO forKey:kAppiraterRated]; - [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; - [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; - } + // check if the first use date has been set. if not, set it. + NSTimeInterval timeInterval = [userDefaults doubleForKey:kAppiraterFirstUseDate]; + if (timeInterval == 0) + { + timeInterval = [[NSDate date] timeIntervalSince1970]; + [userDefaults setDouble:timeInterval forKey:kAppiraterFirstUseDate]; + } + + // increment the significant event count + NSInteger sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount]; + sigEventCount++; + [userDefaults setInteger:sigEventCount forKey:kAppiraterSignificantEventCount]; + + if (_debug) + NSLog(@"APPIRATER Significant event count: %@", @(sigEventCount)); [userDefaults synchronize]; } From dd47b738574e0261df3e98c59d2d994bc5263200 Mon Sep 17 00:00:00 2001 From: Jacob Eiting Date: Wed, 9 Sep 2015 10:24:30 -0700 Subject: [PATCH 09/16] Fix tabbing. --- Appirater.m | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Appirater.m b/Appirater.m index f38ce26f..0fa57d02 100644 --- a/Appirater.m +++ b/Appirater.m @@ -337,12 +337,12 @@ - (void)incrementUseCount { { trackingVersion = version; [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; - [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterFirstUseDate]; - [userDefaults setInteger:0 forKey:kAppiraterUseCount]; - [userDefaults setInteger:0 forKey:kAppiraterSignificantEventCount]; - [userDefaults setBool:NO forKey:kAppiraterRated]; - [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; - [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; + [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterFirstUseDate]; + [userDefaults setInteger:0 forKey:kAppiraterUseCount]; + [userDefaults setInteger:0 forKey:kAppiraterSignificantEventCount]; + [userDefaults setBool:NO forKey:kAppiraterRated]; + [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; + [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; } if (_debug) @@ -377,12 +377,12 @@ - (void)incrementSignificantEventCount { { trackingVersion = version; [userDefaults setObject:version forKey:kAppiraterCurrentVersion]; - [userDefaults setDouble:0 forKey:kAppiraterFirstUseDate]; - [userDefaults setInteger:0 forKey:kAppiraterUseCount]; - [userDefaults setInteger:0 forKey:kAppiraterSignificantEventCount]; - [userDefaults setBool:NO forKey:kAppiraterRated]; - [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; - [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; + [userDefaults setDouble:0 forKey:kAppiraterFirstUseDate]; + [userDefaults setInteger:0 forKey:kAppiraterUseCount]; + [userDefaults setInteger:0 forKey:kAppiraterSignificantEventCount]; + [userDefaults setBool:NO forKey:kAppiraterRated]; + [userDefaults setBool:NO forKey:kAppiraterDeclinedToRate]; + [userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate]; } if (_debug) From 5b9242d603adc2ec1bdad58e411ecf4666890d80 Mon Sep 17 00:00:00 2001 From: Leandro Lopez Date: Thu, 3 Nov 2016 14:01:11 -0300 Subject: [PATCH 10/16] Replacing NSURLConnection with NSURLSession. --- Appirater.m | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Appirater.m b/Appirater.m index 0fa57d02..0d3f987f 100644 --- a/Appirater.m +++ b/Appirater.m @@ -206,10 +206,17 @@ - (BOOL)connectedToNetwork { BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection; NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"]; - NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0]; - NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self]; - return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO; + NSURLSessionConfiguration* sessionConfiguration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + sessionConfiguration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData; + sessionConfiguration.timeoutIntervalForRequest = 20.0; + + NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; + + NSURLSessionTask *task = [session dataTaskWithURL:testURL]; + [task resume]; + + return ((isReachable && !needsConnection) || nonWiFi) ? ( (task.state != NSURLSessionTaskStateSuspended) ? YES : NO ) : NO; } + (Appirater*)sharedInstance { From 2191c1de70d3835f75f47f1427365e7a09ebf86e Mon Sep 17 00:00:00 2001 From: Arash Payan Date: Fri, 4 Nov 2016 06:20:49 -0700 Subject: [PATCH 11/16] Suppress deprecation warnings related to UIAlertView and calls to set status bar style when using StoreKit (nobody should be using StoreKit anyway) --- Appirater.m | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Appirater.m b/Appirater.m index 0d3f987f..1c972565 100644 --- a/Appirater.m +++ b/Appirater.m @@ -574,11 +574,6 @@ + (void)rateApp { } [[self getRootViewController] presentViewController:storeViewController animated:_usesAnimation completion:^{ [self setModalOpen:YES]; - //Temporarily use a black status bar to match the StoreKit view. - [self setStatusBarStyle:[UIApplication sharedApplication].statusBarStyle]; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000 - [[UIApplication sharedApplication]setStatusBarStyle:UIStatusBarStyleLightContent animated:_usesAnimation]; -#endif }]; //Use the standard openUrl method if StoreKit is unavailable. @@ -677,7 +672,6 @@ - (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewContr //Close the in-app rating (StoreKit) view and restore the previous status bar style. + (void)closeModal { if (_modalOpen) { - [[UIApplication sharedApplication]setStatusBarStyle:_statusBarStyle animated:_usesAnimation]; BOOL usedAnimation = _usesAnimation; [self setModalOpen:NO]; From 04048d5cf7ed67bdac5344790e16a9989f678104 Mon Sep 17 00:00:00 2001 From: Arash Payan Date: Fri, 4 Nov 2016 06:27:47 -0700 Subject: [PATCH 12/16] Use @import instead #import. Now really include the warning suppression code. --- Appirater.h | 11 ++++++++--- Appirater.m | 3 ++- AppiraterDelegate.h | 2 +- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/Appirater.h b/Appirater.h index afd37f09..9099a23f 100644 --- a/Appirater.h +++ b/Appirater.h @@ -34,9 +34,9 @@ * Copyright 2012 Arash Payan. All rights reserved. */ -#import +@import Foundation; +@import StoreKit; #import "AppiraterDelegate.h" -#import extern NSString *const kAppiraterFirstUseDate; extern NSString *const kAppiraterUseCount; @@ -99,11 +99,16 @@ extern NSString *const kAppiraterReminderRequestDate; #define APPIRATER_RATE_LATER NSLocalizedStringFromTableInBundle(@"Remind me later", @"AppiraterLocalizable", [Appirater bundle], nil) @interface Appirater : NSObject { - +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" UIAlertView *ratingAlert; +#pragma clang diagnostic pop } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" @property(nonatomic, strong) UIAlertView *ratingAlert; +#pragma clan diagnostic pop @property(nonatomic) BOOL openInAppStore; #if __has_feature(objc_arc_weak) @property(nonatomic, weak) NSObject *delegate; diff --git a/Appirater.m b/Appirater.m index 1c972565..69206242 100644 --- a/Appirater.m +++ b/Appirater.m @@ -34,8 +34,9 @@ * Copyright 2012 Arash Payan. All rights reserved. */ +@import SystemConfiguration; +@import CFNetwork; #import "Appirater.h" -#import #include #if ! __has_feature(objc_arc) diff --git a/AppiraterDelegate.h b/AppiraterDelegate.h index b5a7d7e7..f7605c4c 100644 --- a/AppiraterDelegate.h +++ b/AppiraterDelegate.h @@ -6,7 +6,7 @@ // Copyright (c) 2012 News.me. All rights reserved. // -#import +@import Foundation; @class Appirater; From 082e53f6300a5ab126e2d5b4fdbe832ff32df5bd Mon Sep 17 00:00:00 2001 From: Alexandre Blin Date: Fri, 4 Nov 2016 15:50:20 +0100 Subject: [PATCH 13/16] Fix typo in #pragma line --- Appirater.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Appirater.h b/Appirater.h index 9099a23f..51837f08 100644 --- a/Appirater.h +++ b/Appirater.h @@ -108,7 +108,7 @@ extern NSString *const kAppiraterReminderRequestDate; #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" @property(nonatomic, strong) UIAlertView *ratingAlert; -#pragma clan diagnostic pop +#pragma clang diagnostic pop @property(nonatomic) BOOL openInAppStore; #if __has_feature(objc_arc_weak) @property(nonatomic, weak) NSObject *delegate; From e82c7ca2a12baf394ddf09b079efa3279da3250a Mon Sep 17 00:00:00 2001 From: Reiner Pittinger Date: Fri, 11 Nov 2016 01:14:46 +0100 Subject: [PATCH 14/16] Use #import instead of @import (#246) Use #import instead of @import --- Appirater.h | 4 ++-- Appirater.m | 4 ++-- AppiraterDelegate.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Appirater.h b/Appirater.h index 51837f08..f556b370 100644 --- a/Appirater.h +++ b/Appirater.h @@ -34,8 +34,8 @@ * Copyright 2012 Arash Payan. All rights reserved. */ -@import Foundation; -@import StoreKit; +#import +#import #import "AppiraterDelegate.h" extern NSString *const kAppiraterFirstUseDate; diff --git a/Appirater.m b/Appirater.m index 69206242..ed4962bc 100644 --- a/Appirater.m +++ b/Appirater.m @@ -34,8 +34,8 @@ * Copyright 2012 Arash Payan. All rights reserved. */ -@import SystemConfiguration; -@import CFNetwork; +#import +#import #import "Appirater.h" #include diff --git a/AppiraterDelegate.h b/AppiraterDelegate.h index f7605c4c..b5a7d7e7 100644 --- a/AppiraterDelegate.h +++ b/AppiraterDelegate.h @@ -6,7 +6,7 @@ // Copyright (c) 2012 News.me. All rights reserved. // -@import Foundation; +#import @class Appirater; From 14ce5a87331f7b740d9f97e7a934e7730e49df1b Mon Sep 17 00:00:00 2001 From: Matthew Sun Date: Tue, 10 Jan 2017 21:40:10 -0800 Subject: [PATCH 15/16] suppress UIAlertView warnings in Appirater.m --- Appirater.m | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Appirater.m b/Appirater.m index ed4962bc..2ad36720 100644 --- a/Appirater.m +++ b/Appirater.m @@ -251,7 +251,10 @@ - (void)showRatingAlert } - (void)reallyShowPreliminaryAlert { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_PRELIMINARY_MESSAGE_TITLE +#pragma clang diagnostic pop message:APPIRATER_PRELIMINARY_MESSAGE delegate:self cancelButtonTitle:APPIRATER_PRELIMINARY_MESSAGE_NO_BUTTON @@ -268,15 +271,24 @@ - (void)reallyShowPreliminaryAlert { } - (void)reallyShowRatingAlert:(BOOL)displayRateLaterButton { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" UIAlertView *alertView = nil; +#pragma clang diagnostic pop if (displayRateLaterButton) { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE +#pragma clang diagnostic pop message:APPIRATER_MESSAGE delegate:self cancelButtonTitle:APPIRATER_CANCEL_BUTTON otherButtonTitles:APPIRATER_RATE_BUTTON, APPIRATER_RATE_LATER, nil]; } else { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE +#pragma clang diagnostic pop message:APPIRATER_MESSAGE delegate:self cancelButtonTitle:APPIRATER_CANCEL_BUTTON @@ -595,7 +607,11 @@ + (void)rateApp { } } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#pragma clang diagnostic ignored "-Wdeprecated-implementations" - (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { +#pragma clang diagnostic push NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; id delegate = _delegate; From 9c99b6f494f2636ebcf663b4c929250cec20997e Mon Sep 17 00:00:00 2001 From: Matthew Sun Date: Mon, 25 Sep 2017 17:05:36 -0700 Subject: [PATCH 16/16] update openURL: for iOS10 --- Appirater.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Appirater.m b/Appirater.m index 2ad36720..edf8e862 100644 --- a/Appirater.m +++ b/Appirater.m @@ -602,7 +602,9 @@ + (void)rateApp { reviewURL = [templateReviewURLiOS7 stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]]; } - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:reviewURL]]; + [UIApplication.sharedApplication openURL:[NSURL URLWithString:reviewURL] + options:@{} + completionHandler:nil]; #endif } }