From ab67f92f3d8df728199449c03b7b37ee3a32f985 Mon Sep 17 00:00:00 2001 From: Hari Karam Singh Date: Fri, 23 Mar 2012 09:48:17 +0000 Subject: [PATCH 1/3] ifdef wrappers to allow settings without overwriting the files --- Appirater.h | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/Appirater.h b/Appirater.h index ce109d03..61ec3cc5 100644 --- a/Appirater.h +++ b/Appirater.h @@ -47,47 +47,68 @@ extern NSString *const kAppiraterReminderRequestDate; /* Place your Apple generated software id here. */ +#ifndef APPIRATER_APP_ID #define APPIRATER_APP_ID 301377083 - +#endif /* Your app's name. */ +#ifndef APPIRATER_APP_NAME #define APPIRATER_APP_NAME [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey] +#endif /* This is the message your users will see once they've passed the day+launches threshold. */ +#ifndef APPIRATER_LOCALIZED_MESSAGE #define APPIRATER_LOCALIZED_MESSAGE NSLocalizedString(@"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!", nil) +#endif +#ifndef APPIRATER_MESSAGE #define APPIRATER_MESSAGE [NSString stringWithFormat:APPIRATER_LOCALIZED_MESSAGE, APPIRATER_APP_NAME] +#endif /* This is the title of the message alert that users will see. */ +#ifndef APPIRATER_LOCALIZED_MESSAGE_TITLE #define APPIRATER_LOCALIZED_MESSAGE_TITLE NSLocalizedString(@"Rate %@", nil) +#endif +#ifndef APPIRATER_MESSAGE_TITLE #define APPIRATER_MESSAGE_TITLE [NSString stringWithFormat:APPIRATER_LOCALIZED_MESSAGE_TITLE, APPIRATER_APP_NAME] +#endif /* The text of the button that rejects reviewing the app. */ +#ifndef APPIRATER_CANCEL_BUTTON #define APPIRATER_CANCEL_BUTTON NSLocalizedString(@"No, Thanks", nil) +#endif /* Text of button that will send user to app review page. */ +#ifndef APPIRATER_LOCALIZED_RATE_BUTTON #define APPIRATER_LOCALIZED_RATE_BUTTON NSLocalizedString(@"Rate %@", nil) +#endif +#ifndef APPIRATER_RATE_BUTTON #define APPIRATER_RATE_BUTTON [NSString stringWithFormat:APPIRATER_LOCALIZED_RATE_BUTTON, APPIRATER_APP_NAME] +#endif /* Text for button to remind the user to review later. */ +#ifndef APPIRATER_RATE_LATER #define APPIRATER_RATE_LATER NSLocalizedString(@"Remind me later", nil) +#endif /* Users will need to have the same version of your app installed for this many days before they will be prompted to rate it. */ +#ifndef APPIRATER_DAYS_UNTIL_PROMPT #define APPIRATER_DAYS_UNTIL_PROMPT 30 // double +#endif /* An example of a 'use' would be if the user launched the app. Bringing the app @@ -99,7 +120,9 @@ extern NSString *const kAppiraterReminderRequestDate; Users need to 'use' the same version of the app this many times before before they will be prompted to rate it. */ +#ifndef APPIRATER_USES_UNTIL_PROMPT #define APPIRATER_USES_UNTIL_PROMPT 20 // integer +#endif /* A significant event can be anything you want to be in your app. In a @@ -112,20 +135,26 @@ extern NSString *const kAppiraterReminderRequestDate; a significant event, call the method: [Appirater userDidSignificantEvent:]; */ +#ifndef APPIRATER_SIG_EVENTS_UNTIL_PROMPT #define APPIRATER_SIG_EVENTS_UNTIL_PROMPT -1 // integer +#endif /* Once the rating alert is presented to the user, they might select 'Remind me later'. This value specifies how long (in days) Appirater will wait before reminding them. */ +#ifndef APPIRATER_TIME_BEFORE_REMINDING #define APPIRATER_TIME_BEFORE_REMINDING 1 // double +#endif /* 'YES' will show the Appirater alert everytime. Useful for testing how your message looks and making sure the link to your app's review page works. */ +#ifndef APPIRATER_DEBUG #define APPIRATER_DEBUG NO +#endif @interface Appirater : NSObject { From fdc6198e09aa0e8f962a3777e6d82f9b348862ba Mon Sep 17 00:00:00 2001 From: Hari Karam Singh Date: Fri, 23 Mar 2012 11:16:59 +0000 Subject: [PATCH 2/3] Adds additional DEBUG macros for simulating various user states such as 'use count' and 'days since first use' --- Appirater.h | 21 +++++++++++++++++++++ Appirater.m | 38 +++++++++++++++++++++++++++++++------- 2 files changed, 52 insertions(+), 7 deletions(-) diff --git a/Appirater.h b/Appirater.h index 61ec3cc5..9a73a353 100644 --- a/Appirater.h +++ b/Appirater.h @@ -156,6 +156,27 @@ extern NSString *const kAppiraterReminderRequestDate; #define APPIRATER_DEBUG NO #endif +/* + Used simulate usage cases to test popup. Generally, you'll want to set one + or two of them and test the others. -1 == disabled. Leave APPIRATER_DEBUG + set to NO in order to use these. + */ +#ifndef APPIRATER_DEBUG_DAYS_LAPSED_OVERRIDE +#define APPIRATER_DEBUG_DAYS_LAPSED_OVERRIDE -1 +#endif +#ifndef APPIRATER_DEBUG_USE_COUNT_OVERRIDE +#define APPIRATER_DEBUG_USE_COUNT_OVERRIDE -1 +#endif +#ifndef APPIRATER_DEBUG_SIG_EVENTS_COUNT_OVERRIDE +#define APPIRATER_DEBUG_SIG_EVENTS_COUNT_OVERRIDE -1 +#endif +#ifndef APPIRATER_DEBUG_DAYS_LAPSED_SINCE_REMINDER_OVERRIDE +#define APPIRATER_DEBUG_DAYS_LAPSED_SINCE_REMINDER_OVERRIDE -1 +#endif + + + + @interface Appirater : NSObject { UIAlertView *ratingAlert; diff --git a/Appirater.m b/Appirater.m index 3c99b5a5..8149512b 100644 --- a/Appirater.m +++ b/Appirater.m @@ -124,18 +124,34 @@ - (BOOL)ratingConditionsHaveBeenMet { NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; NSDate *dateOfFirstLaunch = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterFirstUseDate]]; - NSTimeInterval timeSinceFirstLaunch = [[NSDate date] timeIntervalSinceDate:dateOfFirstLaunch]; - NSTimeInterval timeUntilRate = 60 * 60 * 24 * APPIRATER_DAYS_UNTIL_PROMPT; + NSTimeInterval timeSinceFirstLaunch; + if (APPIRATER_DEBUG_DAYS_LAPSED_OVERRIDE >= 0) { + timeSinceFirstLaunch = 60 * 60 * 24 * APPIRATER_DEBUG_DAYS_LAPSED_OVERRIDE; + } else { + timeSinceFirstLaunch = [[NSDate date] timeIntervalSinceDate:dateOfFirstLaunch]; + } + NSTimeInterval timeUntilRate = 60 * 60 * 24 * APPIRATER_DAYS_UNTIL_PROMPT; + if (timeSinceFirstLaunch < timeUntilRate) return NO; // check if the app has been used enough - int useCount = [userDefaults integerForKey:kAppiraterUseCount]; + int useCount; + if (APPIRATER_DEBUG_USE_COUNT_OVERRIDE >= 0) { + useCount = APPIRATER_DEBUG_USE_COUNT_OVERRIDE; + } else { + useCount = [userDefaults integerForKey:kAppiraterUseCount]; + } if (useCount <= APPIRATER_USES_UNTIL_PROMPT) return NO; // check if the user has done enough significant events - int sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount]; + int sigEventCount; + if (APPIRATER_DEBUG_SIG_EVENTS_COUNT_OVERRIDE >= 0) { + sigEventCount = APPIRATER_DEBUG_SIG_EVENTS_COUNT_OVERRIDE; + } else { + sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount]; + } if (sigEventCount <= APPIRATER_SIG_EVENTS_UNTIL_PROMPT) return NO; @@ -149,7 +165,12 @@ - (BOOL)ratingConditionsHaveBeenMet { // if the user wanted to be reminded later, has enough time passed? NSDate *reminderRequestDate = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterReminderRequestDate]]; - NSTimeInterval timeSinceReminderRequest = [[NSDate date] timeIntervalSinceDate:reminderRequestDate]; + NSTimeInterval timeSinceReminderRequest; + if (APPIRATER_DEBUG_DAYS_LAPSED_SINCE_REMINDER_OVERRIDE >= 0) { + timeSinceReminderRequest = 60 * 60 * 24 *APPIRATER_DEBUG_DAYS_LAPSED_SINCE_REMINDER_OVERRIDE; + } else { + timeSinceReminderRequest = [[NSDate date] timeIntervalSinceDate:reminderRequestDate]; + } NSTimeInterval timeUntilReminder = 60 * 60 * 24 * APPIRATER_TIME_BEFORE_REMINDING; if (timeSinceReminderRequest < timeUntilReminder) return NO; @@ -187,8 +208,11 @@ - (void)incrementUseCount { int useCount = [userDefaults integerForKey:kAppiraterUseCount]; useCount++; [userDefaults setInteger:useCount forKey:kAppiraterUseCount]; - if (APPIRATER_DEBUG) - NSLog(@"APPIRATER Use count: %d", useCount); + if (APPIRATER_DEBUG) { + NSLog(@"APPIRATER Use count: %d", useCount); + } else if (APPIRATER_DEBUG_USE_COUNT_OVERRIDE > -1) { + NSLog(@"APPIRATER Use count (debug override): %d", APPIRATER_DEBUG_USE_COUNT_OVERRIDE); + } } else { From 540e56cf328cf43245c93dd5cc12875855c63345 Mon Sep 17 00:00:00 2001 From: Hari Karam Singh Date: Sun, 25 Mar 2012 13:52:34 +0100 Subject: [PATCH 3/3] Added NSNotification dispatches for button presses to allow external hooks. --- Appirater.h | 11 +++++++++++ Appirater.m | 25 +++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/Appirater.h b/Appirater.h index 9a73a353..8d33327b 100644 --- a/Appirater.h +++ b/Appirater.h @@ -44,6 +44,17 @@ extern NSString *const kAppiraterRatedCurrentVersion; extern NSString *const kAppiraterDeclinedToRate; extern NSString *const kAppiraterReminderRequestDate; +/* + NSNotification name for popup click event + */ +extern NSString *const kAppiraterButtonClickedNotification; + +/* Sent as the object to the above notification on click */ +extern NSString *const kAppiraterNotificationObjectForDeclinedClicked; +extern NSString *const kAppiraterNotificationObjectForRateClicked; +extern NSString *const kAppiraterNotificationObjectForLaterClicked; +extern NSString *const kAppiraterNotificationObjectForOtherClicked; + /* Place your Apple generated software id here. */ diff --git a/Appirater.m b/Appirater.m index 8149512b..3ad96915 100644 --- a/Appirater.m +++ b/Appirater.m @@ -48,6 +48,14 @@ NSString *templateReviewURL = @"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=APP_ID"; +/** Notification message & objects */ +NSString *const kAppiraterButtonClickedNotification = @"kAppiraterButtonClickedNotification"; +NSString *const kAppiraterNotificationObjectForDeclinedClicked = @"kAppiraterNotificationObjectForDeclinedClicked"; +NSString *const kAppiraterNotificationObjectForRateClicked = @"kAppiraterNotificationObjectForRateClicked"; +NSString *const kAppiraterNotificationObjectForLaterClicked = @"kAppiraterNotificationObjectForLaterClicked"; +NSString *const kAppiraterNotificationObjectForOtherClicked = @"kAppiraterNotificationObjectForOtherClicked"; + + @interface Appirater () - (BOOL)connectedToNetwork; + (Appirater*)sharedInstance; @@ -359,28 +367,45 @@ + (void)rateApp { - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; + NSString *notifObj; + switch (buttonIndex) { case 0: { // they don't want to rate it [userDefaults setBool:YES forKey:kAppiraterDeclinedToRate]; [userDefaults synchronize]; + + // Msg for notification + notifObj = kAppiraterNotificationObjectForDeclinedClicked; + break; } case 1: { // they want to rate it [Appirater rateApp]; + + notifObj = kAppiraterNotificationObjectForRateClicked; + break; } case 2: // remind them later [userDefaults setDouble:[[NSDate date] timeIntervalSince1970] forKey:kAppiraterReminderRequestDate]; [userDefaults synchronize]; + + notifObj = kAppiraterNotificationObjectForLaterClicked; + break; default: + + notifObj = kAppiraterNotificationObjectForOtherClicked; break; } + + // Send the notification + [[NSNotificationCenter defaultCenter] postNotificationName:kAppiraterButtonClickedNotification object:notifObj]; } @end