Skip to content
This repository
Browse code

Merge pull request #58 from robotmedia/master

Dynamic configuration + ARC
  • Loading branch information...
commit da20fe69967ce7b5d5b3de0ad89af335e78bde4a 2 parents fe6c9a2 + f876e29
Arash Payan authored

Showing 4 changed files with 119 additions and 75 deletions. Show diff stats Hide diff stats

  1. +2 0  .gitignore
  2. +68 58 Appirater.h
  3. +48 16 Appirater.m
  4. +1 1  README.md
2  .gitignore
... ... @@ -0,0 +1,2 @@
  1 +
  2 +.DS_Store
126 Appirater.h
@@ -45,12 +45,6 @@ extern NSString *const kAppiraterDeclinedToRate;
45 45 extern NSString *const kAppiraterReminderRequestDate;
46 46
47 47 /*
48   - Place your Apple generated software id here.
49   - */
50   -#define APPIRATER_APP_ID 301377083
51   -
52   -
53   -/*
54 48 Your localized app's name.
55 49 */
56 50 #define APPIRATER_LOCALIZED_APP_NAME [[[NSBundle mainBundle] localizedInfoDictionary] objectForKey:(NSString *)kCFBundleNameKey]
@@ -89,64 +83,13 @@ extern NSString *const kAppiraterReminderRequestDate;
89 83 */
90 84 #define APPIRATER_RATE_LATER NSLocalizedString(@"Remind me later", nil)
91 85
92   -/*
93   - Users will need to have the same version of your app installed for this many
94   - days before they will be prompted to rate it.
95   - */
96   -#define APPIRATER_DAYS_UNTIL_PROMPT 30 // double
97   -
98   -/*
99   - An example of a 'use' would be if the user launched the app. Bringing the app
100   - into the foreground (on devices that support it) would also be considered
101   - a 'use'. You tell Appirater about these events using the two methods:
102   - [Appirater appLaunched:]
103   - [Appirater appEnteredForeground:]
104   -
105   - Users need to 'use' the same version of the app this many times before
106   - before they will be prompted to rate it.
107   - */
108   -#define APPIRATER_USES_UNTIL_PROMPT 20 // integer
109   -
110   -/*
111   - A significant event can be anything you want to be in your app. In a
112   - telephone app, a significant event might be placing or receiving a call.
113   - In a game, it might be beating a level or a boss. This is just another
114   - layer of filtering that can be used to make sure that only the most
115   - loyal of your users are being prompted to rate you on the app store.
116   - If you leave this at a value of -1, then this won't be a criteria
117   - used for rating. To tell Appirater that the user has performed
118   - a significant event, call the method:
119   - [Appirater userDidSignificantEvent:];
120   - */
121   -#define APPIRATER_SIG_EVENTS_UNTIL_PROMPT -1 // integer
122   -
123   -/*
124   - Once the rating alert is presented to the user, they might select
125   - 'Remind me later'. This value specifies how long (in days) Appirater
126   - will wait before reminding them.
127   - */
128   -#define APPIRATER_TIME_BEFORE_REMINDING 1 // double
129   -
130   -/*
131   - 'YES' will show the Appirater alert everytime. Useful for testing how your message
132   - looks and making sure the link to your app's review page works.
133   - */
134   -#define APPIRATER_DEBUG YES
135 86
136 87 @interface Appirater : NSObject <UIAlertViewDelegate> {
137 88
138 89 UIAlertView *ratingAlert;
139 90 }
140 91
141   -@property(nonatomic, retain) UIAlertView *ratingAlert;
142   -
143   -/*
144   - DEPRECATED: While still functional, it's better to use
145   - appLaunched:(BOOL)canPromptForRating instead.
146   -
147   - Calls [Appirater appLaunched:YES]. See appLaunched: for details of functionality.
148   - */
149   -+ (void)appLaunched;
  92 +@property(nonatomic, strong) UIAlertView *ratingAlert;
150 93
151 94 /*
152 95 Tells Appirater that the app has launched, and on devices that do NOT
@@ -207,3 +150,70 @@ extern NSString *const kAppiraterReminderRequestDate;
207 150 + (void)rateApp;
208 151
209 152 @end
  153 +
  154 +@interface Appirater(Configuration)
  155 +
  156 +/*
  157 + Set your Apple generated software id here.
  158 + */
  159 ++ (void) setAppId:(NSString*)appId;
  160 +
  161 +/*
  162 + Users will need to have the same version of your app installed for this many
  163 + days before they will be prompted to rate it.
  164 + */
  165 ++ (void) setDaysUntilPrompt:(double)value;
  166 +
  167 +/*
  168 + An example of a 'use' would be if the user launched the app. Bringing the app
  169 + into the foreground (on devices that support it) would also be considered
  170 + a 'use'. You tell Appirater about these events using the two methods:
  171 + [Appirater appLaunched:]
  172 + [Appirater appEnteredForeground:]
  173 +
  174 + Users need to 'use' the same version of the app this many times before
  175 + before they will be prompted to rate it.
  176 + */
  177 ++ (void) setUsesUntilPrompt:(NSInteger)value;
  178 +
  179 +/*
  180 + A significant event can be anything you want to be in your app. In a
  181 + telephone app, a significant event might be placing or receiving a call.
  182 + In a game, it might be beating a level or a boss. This is just another
  183 + layer of filtering that can be used to make sure that only the most
  184 + loyal of your users are being prompted to rate you on the app store.
  185 + If you leave this at a value of -1, then this won't be a criteria
  186 + used for rating. To tell Appirater that the user has performed
  187 + a significant event, call the method:
  188 + [Appirater userDidSignificantEvent:];
  189 + */
  190 ++ (void) setSignificantEventsUntilPrompt:(NSInteger)value;
  191 +
  192 +
  193 +/*
  194 + Once the rating alert is presented to the user, they might select
  195 + 'Remind me later'. This value specifies how long (in days) Appirater
  196 + will wait before reminding them.
  197 + */
  198 ++ (void) setTimeBeforeReminding:(double)value;
  199 +
  200 +/*
  201 + 'YES' will show the Appirater alert everytime. Useful for testing how your message
  202 + looks and making sure the link to your app's review page works.
  203 + */
  204 ++ (void) setDebug:(BOOL)debug;
  205 +
  206 +@end
  207 +
  208 +
  209 +@interface Appirater(Deprecated)
  210 +
  211 +/*
  212 + DEPRECATED: While still functional, it's better to use
  213 + appLaunched:(BOOL)canPromptForRating instead.
  214 +
  215 + Calls [Appirater appLaunched:YES]. See appLaunched: for details of functionality.
  216 + */
  217 ++ (void)appLaunched __attribute__((deprecated));
  218 +
  219 +@end
64 Appirater.m
@@ -49,6 +49,13 @@
49 49 NSString *templateReviewURL = @"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=APP_ID";
50 50 NSString *templateReviewURLiOS6 = @"itms-apps://itunes.apple.com/LANGUAGE/app/idAPP_ID";
51 51
  52 +static NSString *_appId;
  53 +static double _daysUntilPrompt = 30;
  54 +static NSInteger _usesUntilPrompt = 20;
  55 +static NSInteger _significantEventsUntilPrompt = -1;
  56 +static double _timeBeforeReminding = 1;
  57 +static BOOL _debug = NO;
  58 +
52 59 @interface Appirater ()
53 60 - (BOOL)connectedToNetwork;
54 61 + (Appirater*)sharedInstance;
@@ -62,6 +69,31 @@ @implementation Appirater
62 69
63 70 @synthesize ratingAlert;
64 71
  72 ++ (void) setAppId:(NSString *)appId {
  73 + _appId = appId;
  74 +}
  75 +
  76 ++ (void) setDaysUntilPrompt:(double)value {
  77 + _daysUntilPrompt = value;
  78 +}
  79 +
  80 ++ (void) setUsesUntilPrompt:(NSInteger)value {
  81 + _usesUntilPrompt = value;
  82 +}
  83 +
  84 ++ (void) setSignificantEventsUntilPrompt:(NSInteger)value {
  85 + _significantEventsUntilPrompt = value;
  86 +}
  87 +
  88 ++ (void) setTimeBeforeReminding:(double)value {
  89 + _timeBeforeReminding = value;
  90 +}
  91 +
  92 ++ (void) setDebug:(BOOL)debug {
  93 + _debug = debug;
  94 +}
  95 +
  96 +
65 97 - (BOOL)connectedToNetwork {
66 98 // Create zero addy
67 99 struct sockaddr_in zeroAddress;
@@ -88,7 +120,7 @@ - (BOOL)connectedToNetwork {
88 120
89 121 NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"];
90 122 NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:20.0];
91   - NSURLConnection *testConnection = [[[NSURLConnection alloc] initWithRequest:testRequest delegate:self] autorelease];
  123 + NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self];
92 124
93 125 return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO;
94 126 }
@@ -109,35 +141,35 @@ + (Appirater*)sharedInstance {
109 141 }
110 142
111 143 - (void)showRatingAlert {
112   - UIAlertView *alertView = [[[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE
  144 + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:APPIRATER_MESSAGE_TITLE
113 145 message:APPIRATER_MESSAGE
114 146 delegate:self
115 147 cancelButtonTitle:APPIRATER_CANCEL_BUTTON
116   - otherButtonTitles:APPIRATER_RATE_BUTTON, APPIRATER_RATE_LATER, nil] autorelease];
  148 + otherButtonTitles:APPIRATER_RATE_BUTTON, APPIRATER_RATE_LATER, nil];
117 149 self.ratingAlert = alertView;
118 150 [alertView show];
119 151 }
120 152
121 153 - (BOOL)ratingConditionsHaveBeenMet {
122   - if (APPIRATER_DEBUG)
  154 + if (_debug)
123 155 return YES;
124 156
125 157 NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
126 158
127 159 NSDate *dateOfFirstLaunch = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterFirstUseDate]];
128 160 NSTimeInterval timeSinceFirstLaunch = [[NSDate date] timeIntervalSinceDate:dateOfFirstLaunch];
129   - NSTimeInterval timeUntilRate = 60 * 60 * 24 * APPIRATER_DAYS_UNTIL_PROMPT;
  161 + NSTimeInterval timeUntilRate = 60 * 60 * 24 * _daysUntilPrompt;
130 162 if (timeSinceFirstLaunch < timeUntilRate)
131 163 return NO;
132 164
133 165 // check if the app has been used enough
134 166 int useCount = [userDefaults integerForKey:kAppiraterUseCount];
135   - if (useCount <= APPIRATER_USES_UNTIL_PROMPT)
  167 + if (useCount <= _usesUntilPrompt)
136 168 return NO;
137 169
138 170 // check if the user has done enough significant events
139 171 int sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount];
140   - if (sigEventCount <= APPIRATER_SIG_EVENTS_UNTIL_PROMPT)
  172 + if (sigEventCount <= _significantEventsUntilPrompt)
141 173 return NO;
142 174
143 175 // has the user previously declined to rate this version of the app?
@@ -151,7 +183,7 @@ - (BOOL)ratingConditionsHaveBeenMet {
151 183 // if the user wanted to be reminded later, has enough time passed?
152 184 NSDate *reminderRequestDate = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterReminderRequestDate]];
153 185 NSTimeInterval timeSinceReminderRequest = [[NSDate date] timeIntervalSinceDate:reminderRequestDate];
154   - NSTimeInterval timeUntilReminder = 60 * 60 * 24 * APPIRATER_TIME_BEFORE_REMINDING;
  186 + NSTimeInterval timeUntilReminder = 60 * 60 * 24 * _timeBeforeReminding;
155 187 if (timeSinceReminderRequest < timeUntilReminder)
156 188 return NO;
157 189
@@ -171,7 +203,7 @@ - (void)incrementUseCount {
171 203 [userDefaults setObject:version forKey:kAppiraterCurrentVersion];
172 204 }
173 205
174   - if (APPIRATER_DEBUG)
  206 + if (_debug)
175 207 NSLog(@"APPIRATER Tracking version: %@", trackingVersion);
176 208
177 209 if ([trackingVersion isEqualToString:version])
@@ -188,7 +220,7 @@ - (void)incrementUseCount {
188 220 int useCount = [userDefaults integerForKey:kAppiraterUseCount];
189 221 useCount++;
190 222 [userDefaults setInteger:useCount forKey:kAppiraterUseCount];
191   - if (APPIRATER_DEBUG)
  223 + if (_debug)
192 224 NSLog(@"APPIRATER Use count: %d", useCount);
193 225 }
194 226 else
@@ -219,7 +251,7 @@ - (void)incrementSignificantEventCount {
219 251 [userDefaults setObject:version forKey:kAppiraterCurrentVersion];
220 252 }
221 253
222   - if (APPIRATER_DEBUG)
  254 + if (_debug)
223 255 NSLog(@"APPIRATER Tracking version: %@", trackingVersion);
224 256
225 257 if ([trackingVersion isEqualToString:version])
@@ -236,7 +268,7 @@ - (void)incrementSignificantEventCount {
236 268 int sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount];
237 269 sigEventCount++;
238 270 [userDefaults setInteger:sigEventCount forKey:kAppiraterSignificantEventCount];
239   - if (APPIRATER_DEBUG)
  271 + if (_debug)
240 272 NSLog(@"APPIRATER Significant event count: %d", sigEventCount);
241 273 }
242 274 else
@@ -295,14 +327,14 @@ + (void)appLaunched:(BOOL)canPromptForRating {
295 327
296 328 - (void)hideRatingAlert {
297 329 if (self.ratingAlert.visible) {
298   - if (APPIRATER_DEBUG)
  330 + if (_debug)
299 331 NSLog(@"APPIRATER Hiding Alert");
300 332 [self.ratingAlert dismissWithClickedButtonIndex:-1 animated:NO];
301 333 }
302 334 }
303 335
304 336 + (void)appWillResignActive {
305   - if (APPIRATER_DEBUG)
  337 + if (_debug)
306 338 NSLog(@"APPIRATER appWillResignActive");
307 339 [[Appirater sharedInstance] hideRatingAlert];
308 340 }
@@ -330,12 +362,12 @@ + (void)rateApp {
330 362 // added work arround for wrong URL Scheme used in new App store on iOS 6
331 363 NSString *reviewURL;
332 364 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0) {
333   - reviewURL = [templateReviewURLiOS6 stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%d", APPIRATER_APP_ID]];
  365 + reviewURL = [templateReviewURLiOS6 stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]];
334 366
335 367 reviewURL = [reviewURL stringByReplacingOccurrencesOfString:@"LANGUAGE" withString:[NSString stringWithFormat:@"%@", [[NSLocale preferredLanguages] objectAtIndex:0]]];
336 368
337 369 } else {
338   - reviewURL = [templateReviewURL stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%d", APPIRATER_APP_ID]];
  370 + reviewURL = [templateReviewURL stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]];
339 371 }
340 372
341 373 [userDefaults setBool:YES forKey:kAppiraterRatedCurrentVersion];
2  README.md
Source Rendered
@@ -13,7 +13,7 @@ Getting Started
13 13 3. Call `[Appirater appLaunched:YES]` at the end of your app delegate's `application:didFinishLaunchingWithOptions:` method.
14 14 4. Call `[Appirater appEnteredForeground:YES]` in your app delegate's `applicationWillEnterForeground:` method.
15 15 5. (OPTIONAL) Call `[Appirater userDidSignificantEvent:YES]` when the user does something 'significant' in the app.
16   -6. Finally, set the `APPIRATER_APP_ID` in `Appirater.h` to your Apple provided software id.
  16 +6. Finally, call `[Appirater setAppId:@"yourAppId"]` with your Apple provided software id.
17 17
18 18 License
19 19 -------

0 comments on commit da20fe6

Please sign in to comment.
Something went wrong with that request. Please try again.