iphone: Drop unused Appirater thirdparty API

This commit is contained in:
Rémi Verschelde 2017-03-05 14:53:56 +01:00
parent 49c065d29c
commit 481e511082
6 changed files with 0 additions and 970 deletions

View file

@ -1,200 +0,0 @@
/*
This file is part of Appirater.
Copyright (c) 2010, Arash Payan
All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Appirater.h
* appirater
*
* Created by Arash Payan on 9/5/09.
* http://arashpayan.com
* Copyright 2010 Arash Payan. All rights reserved.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
extern NSString *const kAppiraterFirstUseDate;
extern NSString *const kAppiraterUseCount;
extern NSString *const kAppiraterSignificantEventCount;
extern NSString *const kAppiraterCurrentVersion;
extern NSString *const kAppiraterRatedCurrentVersion;
extern NSString *const kAppiraterDeclinedToRate;
/*
Place your Apple generated software id here.
*/
#define APPIRATER_APP_ID 301377083
/*
Your app's name.
*/
#define APPIRATER_APP_NAME [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]
/*
This is the message your users will see once they've passed the day+launches
threshold.
*/
#define APPIRATER_MESSAGE [NSString stringWithFormat:@"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!", APPIRATER_APP_NAME]
/*
This is the title of the message alert that users will see.
*/
#define APPIRATER_MESSAGE_TITLE [NSString stringWithFormat:@"Rate %@", APPIRATER_APP_NAME]
/*
The text of the button that rejects reviewing the app.
*/
#define APPIRATER_CANCEL_BUTTON @"No, Thanks"
/*
Text of button that will send user to app review page.
*/
#define APPIRATER_RATE_BUTTON [NSString stringWithFormat:@"Rate %@", APPIRATER_APP_NAME]
/*
Text for button to remind the user to review later.
*/
#define APPIRATER_RATE_LATER @"Remind me later"
/*
Users will need to have the same version of your app installed for this many
days before they will be prompted to rate it.
*/
#define APPIRATER_DAYS_UNTIL_PROMPT 30 // double
/*
An example of a 'use' would be if the user launched the app. Bringing the app
into the foreground (on devices that support it) would also be considered
a 'use'. You tell Appirater about these events using the two methods:
[Appirater appLaunched:]
[Appirater appEnteredForeground:]
Users need to 'use' the same version of the app this many times before
before they will be prompted to rate it.
*/
#define APPIRATER_USES_UNTIL_PROMPT 20 // integer
/*
A significant event can be anything you want to be in your app. In a
telephone app, a significant event might be placing or receiving a call.
In a game, it might be beating a level or a boss. This is just another
layer of filtering that can be used to make sure that only the most
loyal of your users are being prompted to rate you on the app store.
If you leave this at a value of -1, then this won't be a criteria
used for rating. To tell Appirater that the user has performed
a significant event, call the method:
[Appirater userDidSignificantEvent:];
*/
#define APPIRATER_SIG_EVENTS_UNTIL_PROMPT -1 // integer
/*
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.
*/
#define APPIRATER_TIME_BEFORE_REMINDING 1 // double
/*
'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.
*/
#define APPIRATER_DEBUG NO
@interface Appirater : NSObject <UIAlertViewDelegate> {
UIAlertView *ratingAlert;
}
@property(nonatomic, retain) UIAlertView *ratingAlert;
/*
DEPRECATED: While still functional, it's better to use
appLaunched:(BOOL)canPromptForRating instead.
Calls [Appirater appLaunched:YES]. See appLaunched: for details of functionality.
*/
+ (void)appLaunched:(int)p_app_id;
/*
Tells Appirater that the app has launched, and on devices that do NOT
support multitasking, the 'uses' count will be incremented. You should
call this method at the end of your application delegate's
application:didFinishLaunchingWithOptions: method.
If the app has been used enough to be rated (and enough significant events),
you can suppress the rating alert
by passing NO for canPromptForRating. The rating alert will simply be postponed
until it is called again with YES for canPromptForRating. The rating alert
can also be triggered by appEnteredForeground: and userDidSignificantEvent:
(as long as you pass YES for canPromptForRating in those methods).
*/
+ (void)appLaunched:(BOOL)canPromptForRating app_id:(int)p_app_id;
/*
Tells Appirater that the app was brought to the foreground on multitasking
devices. You should call this method from the application delegate's
applicationWillEnterForeground: method.
If the app has been used enough to be rated (and enough significant events),
you can suppress the rating alert
by passing NO for canPromptForRating. The rating alert will simply be postponed
until it is called again with YES for canPromptForRating. The rating alert
can also be triggered by appLaunched: and userDidSignificantEvent:
(as long as you pass YES for canPromptForRating in those methods).
*/
+ (void)appEnteredForeground:(BOOL)canPromptForRating;
/*
Tells Appirater that the user performed a significant event. A significant
event is whatever you want it to be. If you're app is used to make VoIP
calls, then you might want to call this method whenever the user places
a call. If it's a game, you might want to call this whenever the user
beats a level boss.
If the user has performed enough significant events and used the app enough,
you can suppress the rating alert by passing NO for canPromptForRating. The
rating alert will simply be postponed until it is called again with YES for
canPromptForRating. The rating alert can also be triggered by appLaunched:
and appEnteredForeground: (as long as you pass YES for canPromptForRating
in those methods).
*/
+ (void)userDidSignificantEvent:(BOOL)canPromptForRating;
/*
Tells Appirater to open the App Store page where the user can specify a
rating for the app. Also records the fact that this has happened, so the
user won't be prompted again to rate the app.
The only case where you should call this directly is if your app has an
explicit "Rate this app" command somewhere. In all other cases, don't worry
about calling this -- instead, just call the other functions listed above,
and let Appirater handle the bookkeeping of deciding when to ask the user
whether to rate the app.
*/
+ (void)rateApp;
@end

View file

@ -1,732 +0,0 @@
/*
This file is part of Appirater.
Copyright (c) 2012, Arash Payan
All rights reserved.
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Appirater.m
* appirater
*
* Created by Arash Payan on 9/5/09.
* http://arashpayan.com
* Copyright 2012 Arash Payan. All rights reserved.
*/
#import "Appirater.h"
#import <SystemConfiguration/SCNetworkReachability.h>
#include <netinet/in.h>
#if ! __has_feature(objc_arc)
#warning This file must be compiled with ARC. Use -fobjc-arc flag (or convert project to ARC).
#endif
NSString *const kAppiraterFirstUseDate = @"kAppiraterFirstUseDate";
NSString *const kAppiraterUseCount = @"kAppiraterUseCount";
NSString *const kAppiraterSignificantEventCount = @"kAppiraterSignificantEventCount";
NSString *const kAppiraterCurrentVersion = @"kAppiraterCurrentVersion";
NSString *const kAppiraterRatedCurrentVersion = @"kAppiraterRatedCurrentVersion";
NSString *const kAppiraterDeclinedToRate = @"kAppiraterDeclinedToRate";
NSString *const kAppiraterReminderRequestDate = @"kAppiraterReminderRequestDate";
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";
NSString *templateReviewURLiOS8 = @"itms-apps://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=APP_ID&onlyLatestVersion=true&pageNumber=0&sortOrdering=1&type=Purple+Software";
static NSString *_appId;
static double _daysUntilPrompt = 30;
static NSInteger _usesUntilPrompt = 20;
static NSInteger _significantEventsUntilPrompt = -1;
static double _timeBeforeReminding = 1;
static BOOL _debug = NO;
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0
static id<AppiraterDelegate> _delegate;
#else
__weak static id<AppiraterDelegate> _delegate;
#endif
static BOOL _usesAnimation = TRUE;
static UIStatusBarStyle _statusBarStyle;
static BOOL _modalOpen = false;
static BOOL _alwaysUseMainBundle = NO;
@interface Appirater ()
@property (nonatomic, copy) NSString *alertTitle;
@property (nonatomic, copy) NSString *alertMessage;
@property (nonatomic, copy) NSString *alertCancelTitle;
@property (nonatomic, copy) NSString *alertRateTitle;
@property (nonatomic, copy) NSString *alertRateLaterTitle;
- (BOOL)connectedToNetwork;
+ (Appirater*)sharedInstance;
- (void)showPromptWithChecks:(BOOL)withChecks
displayRateLaterButton:(BOOL)displayRateLaterButton;
- (void)showRatingAlert:(BOOL)displayRateLaterButton;
- (void)showRatingAlert;
- (BOOL)ratingAlertIsAppropriate;
- (BOOL)ratingConditionsHaveBeenMet;
- (void)incrementUseCount;
- (void)hideRatingAlert;
@end
@implementation Appirater
@synthesize ratingAlert;
+ (void) setAppId:(NSString *)appId {
_appId = appId;
}
+ (void) setDaysUntilPrompt:(double)value {
_daysUntilPrompt = value;
}
+ (void) setUsesUntilPrompt:(NSInteger)value {
_usesUntilPrompt = value;
}
+ (void) setSignificantEventsUntilPrompt:(NSInteger)value {
_significantEventsUntilPrompt = value;
}
+ (void) setTimeBeforeReminding:(double)value {
_timeBeforeReminding = value;
}
+ (void) setCustomAlertTitle:(NSString *)title
{
[self sharedInstance].alertTitle = title;
}
+ (void) setCustomAlertMessage:(NSString *)message
{
[self sharedInstance].alertMessage = message;
}
+ (void) setCustomAlertCancelButtonTitle:(NSString *)cancelTitle
{
[self sharedInstance].alertCancelTitle = cancelTitle;
}
+ (void) setCustomAlertRateButtonTitle:(NSString *)rateTitle
{
[self sharedInstance].alertRateTitle = rateTitle;
}
+ (void) setCustomAlertRateLaterButtonTitle:(NSString *)rateLaterTitle
{
[self sharedInstance].alertRateLaterTitle = rateLaterTitle;
}
+ (void) setDebug:(BOOL)debug {
_debug = debug;
}
+ (void)setDelegate:(id<AppiraterDelegate>)delegate{
_delegate = delegate;
}
+ (void)setUsesAnimation:(BOOL)animation {
_usesAnimation = animation;
}
+ (void)setOpenInAppStore:(BOOL)openInAppStore {
[Appirater sharedInstance].openInAppStore = openInAppStore;
}
+ (void)setStatusBarStyle:(UIStatusBarStyle)style {
_statusBarStyle = style;
}
+ (void)setModalOpen:(BOOL)open {
_modalOpen = open;
}
+ (void)setAlwaysUseMainBundle:(BOOL)alwaysUseMainBundle {
_alwaysUseMainBundle = alwaysUseMainBundle;
}
+ (NSBundle *)bundle
{
NSBundle *bundle;
if (_alwaysUseMainBundle) {
bundle = [NSBundle mainBundle];
} else {
NSURL *appiraterBundleURL = [[NSBundle mainBundle] URLForResource:@"Appirater" withExtension:@"bundle"];
if (appiraterBundleURL) {
// Appirater.bundle will likely only exist when used via CocoaPods
bundle = [NSBundle bundleWithURL:appiraterBundleURL];
} else {
bundle = [NSBundle mainBundle];
}
}
return bundle;
}
- (NSString *)alertTitle
{
return _alertTitle ? _alertTitle : APPIRATER_MESSAGE_TITLE;
}
- (NSString *)alertMessage
{
return _alertMessage ? _alertMessage : APPIRATER_MESSAGE;
}
- (NSString *)alertCancelTitle
{
return _alertCancelTitle ? _alertCancelTitle : APPIRATER_CANCEL_BUTTON;
}
- (NSString *)alertRateTitle
{
return _alertRateTitle ? _alertRateTitle : APPIRATER_RATE_BUTTON;
}
- (NSString *)alertRateLaterTitle
{
return _alertRateLaterTitle ? _alertRateLaterTitle : APPIRATER_RATE_LATER;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (id)init {
self = [super init];
if (self) {
if ([[UIDevice currentDevice].systemVersion floatValue] >= 7.0) {
self.openInAppStore = YES;
} else {
self.openInAppStore = NO;
}
}
return self;
}
- (BOOL)connectedToNetwork {
// Create zero addy
struct sockaddr_in zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sin_len = sizeof(zeroAddress);
zeroAddress.sin_family = AF_INET;
// Recover reachability flags
SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
SCNetworkReachabilityFlags flags;
Boolean didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
CFRelease(defaultRouteReachability);
if (!didRetrieveFlags)
{
NSLog(@"Error. Could not recover network reachability flags");
return NO;
}
BOOL isReachable = flags & kSCNetworkFlagsReachable;
BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
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;
}
+ (Appirater*)sharedInstance {
static Appirater *appirater = nil;
if (appirater == nil)
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
appirater = [[Appirater alloc] init];
appirater.delegate = _delegate;
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive) name:
UIApplicationWillResignActiveNotification object:nil];
});
}
return appirater;
}
- (void)showRatingAlert:(BOOL)displayRateLaterButton {
UIAlertView *alertView = nil;
id <AppiraterDelegate> delegate = _delegate;
if(delegate && [delegate respondsToSelector:@selector(appiraterShouldDisplayAlert:)] && ![delegate appiraterShouldDisplayAlert:self]) {
return;
}
if (displayRateLaterButton) {
alertView = [[UIAlertView alloc] initWithTitle:self.alertTitle
message:self.alertMessage
delegate:self
cancelButtonTitle:self.alertCancelTitle
otherButtonTitles:self.alertRateTitle, self.alertRateLaterTitle, nil];
} else {
alertView = [[UIAlertView alloc] initWithTitle:self.alertTitle
message:self.alertMessage
delegate:self
cancelButtonTitle:self.alertCancelTitle
otherButtonTitles:self.alertRateTitle, nil];
}
self.ratingAlert = alertView;
[alertView show];
if (delegate && [delegate respondsToSelector:@selector(appiraterDidDisplayAlert:)]) {
[delegate appiraterDidDisplayAlert:self];
}
}
- (void)showRatingAlert
{
[self showRatingAlert:true];
}
// is this an ok time to show the alert? (regardless of whether the rating conditions have been met)
//
// things checked here:
// * connectivity with network
// * whether user has rated before
// * whether user has declined to rate
// * whether rating alert is currently showing visibly
// things NOT checked here:
// * time since first launch
// * number of uses of app
// * number of significant events
// * time since last reminder
- (BOOL)ratingAlertIsAppropriate {
return ([self connectedToNetwork]
&& ![self userHasDeclinedToRate]
&& !self.ratingAlert.visible
&& ![self userHasRatedCurrentVersion]);
}
// have the rating conditions been met/earned? (regardless of whether this would be a moment when it's appropriate to show a new rating alert)
//
// things checked here:
// * time since first launch
// * number of uses of app
// * number of significant events
// * time since last reminder
// things NOT checked here:
// * connectivity with network
// * whether user has rated before
// * whether user has declined to rate
// * whether rating alert is currently showing visibly
- (BOOL)ratingConditionsHaveBeenMet {
if (_debug)
return YES;
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSDate *dateOfFirstLaunch = [NSDate dateWithTimeIntervalSince1970:[userDefaults doubleForKey:kAppiraterFirstUseDate]];
NSTimeInterval timeSinceFirstLaunch = [[NSDate date] timeIntervalSinceDate:dateOfFirstLaunch];
NSTimeInterval timeUntilRate = 60 * 60 * 24 * _daysUntilPrompt;
if (timeSinceFirstLaunch < timeUntilRate)
return NO;
// check if the app has been used enough
NSInteger useCount = [userDefaults integerForKey:kAppiraterUseCount];
if (useCount < _usesUntilPrompt)
return NO;
// check if the user has done enough significant events
NSInteger sigEventCount = [userDefaults integerForKey:kAppiraterSignificantEventCount];
if (sigEventCount < _significantEventsUntilPrompt)
return NO;
// 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 timeUntilReminder = 60 * 60 * 24 * _timeBeforeReminding;
if (timeSinceReminderRequest < timeUntilReminder)
return NO;
return YES;
}
- (void)incrementUseCount {
// get the app's version
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey];
// get the version number that we've been tracking
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion];
if (trackingVersion == nil)
{
trackingVersion = version;
[userDefaults setObject:version forKey:kAppiraterCurrentVersion];
}
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:kAppiraterRatedCurrentVersion];
[userDefaults setBool:NO forKey:kAppiraterDeclinedToRate];
[userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate];
}
[userDefaults synchronize];
}
- (void)incrementSignificantEventCount {
// get the app's version
NSString *version = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleVersionKey];
// get the version number that we've been tracking
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *trackingVersion = [userDefaults stringForKey:kAppiraterCurrentVersion];
if (trackingVersion == nil)
{
trackingVersion = version;
[userDefaults setObject:version forKey:kAppiraterCurrentVersion];
}
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:kAppiraterRatedCurrentVersion];
[userDefaults setBool:NO forKey:kAppiraterDeclinedToRate];
[userDefaults setDouble:0 forKey:kAppiraterReminderRequestDate];
}
[userDefaults synchronize];
}
- (void)incrementAndRate:(BOOL)canPromptForRating {
[self incrementUseCount];
if (canPromptForRating &&
[self ratingConditionsHaveBeenMet] &&
[self ratingAlertIsAppropriate])
{
dispatch_async(dispatch_get_main_queue(),
^{
[self showRatingAlert];
});
}
}
- (void)incrementSignificantEventAndRate:(BOOL)canPromptForRating {
[self incrementSignificantEventCount];
if (canPromptForRating &&
[self ratingConditionsHaveBeenMet] &&
[self ratingAlertIsAppropriate])
{
dispatch_async(dispatch_get_main_queue(),
^{
[self showRatingAlert];
});
}
}
- (BOOL)userHasDeclinedToRate {
return [[NSUserDefaults standardUserDefaults] boolForKey:kAppiraterDeclinedToRate];
}
- (BOOL)userHasRatedCurrentVersion {
return [[NSUserDefaults standardUserDefaults] boolForKey:kAppiraterRatedCurrentVersion];
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-implementations"
+ (void)appLaunched {
[Appirater appLaunched:YES];
}
#pragma GCC diagnostic pop
+ (void)appLaunched:(BOOL)canPromptForRating {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
^{
Appirater *a = [Appirater sharedInstance];
if (_debug) {
dispatch_async(dispatch_get_main_queue(),
^{
[a showRatingAlert];
});
} else {
[a incrementAndRate:canPromptForRating];
}
});
}
- (void)hideRatingAlert {
if (self.ratingAlert.visible) {
if (_debug)
NSLog(@"APPIRATER Hiding Alert");
[self.ratingAlert dismissWithClickedButtonIndex:-1 animated:NO];
}
}
+ (void)appWillResignActive {
if (_debug)
NSLog(@"APPIRATER appWillResignActive");
[[Appirater sharedInstance] hideRatingAlert];
}
+ (void)appEnteredForeground:(BOOL)canPromptForRating {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
^{
[[Appirater sharedInstance] incrementAndRate:canPromptForRating];
});
}
+ (void)userDidSignificantEvent:(BOOL)canPromptForRating {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0),
^{
[[Appirater sharedInstance] incrementSignificantEventAndRate:canPromptForRating];
});
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-implementations"
+ (void)showPrompt {
[Appirater tryToShowPrompt];
}
#pragma GCC diagnostic pop
+ (void)tryToShowPrompt {
[[Appirater sharedInstance] showPromptWithChecks:true
displayRateLaterButton:true];
}
+ (void)forceShowPrompt:(BOOL)displayRateLaterButton {
[[Appirater sharedInstance] showPromptWithChecks:false
displayRateLaterButton:displayRateLaterButton];
}
- (void)showPromptWithChecks:(BOOL)withChecks
displayRateLaterButton:(BOOL)displayRateLaterButton {
if (withChecks == NO || [self ratingAlertIsAppropriate]) {
[self showRatingAlert:displayRateLaterButton];
}
}
+ (id)getRootViewController {
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
if (window.windowLevel != UIWindowLevelNormal) {
NSArray *windows = [[UIApplication sharedApplication] windows];
for(window in windows) {
if (window.windowLevel == UIWindowLevelNormal) {
break;
}
}
}
return [Appirater iterateSubViewsForViewController:window]; // iOS 8+ deep traverse
}
+ (id)iterateSubViewsForViewController:(UIView *) parentView {
for (UIView *subView in [parentView subviews]) {
UIResponder *responder = [subView nextResponder];
if([responder isKindOfClass:[UIViewController class]]) {
return [self topMostViewController: (UIViewController *) responder];
}
id found = [Appirater iterateSubViewsForViewController:subView];
if( nil != found) {
return found;
}
}
return nil;
}
+ (UIViewController *) topMostViewController: (UIViewController *) controller {
BOOL isPresenting = NO;
do {
// this path is called only on iOS 6+, so -presentedViewController is fine here.
UIViewController *presented = [controller presentedViewController];
isPresenting = presented != nil;
if(presented != nil) {
controller = presented;
}
} while (isPresenting);
return controller;
}
+ (void)rateApp {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setBool:YES forKey:kAppiraterRatedCurrentVersion];
[userDefaults synchronize];
//Use the in-app StoreKit view if available (iOS 6) and imported. This works in the simulator.
if (![Appirater sharedInstance].openInAppStore && NSStringFromClass([SKStoreProductViewController class]) != nil) {
SKStoreProductViewController *storeViewController = [[SKStoreProductViewController alloc] init];
NSNumber *appId = [NSNumber numberWithInteger:_appId.integerValue];
[storeViewController loadProductWithParameters:@{SKStoreProductParameterITunesItemIdentifier:appId} completionBlock:nil];
storeViewController.delegate = self.sharedInstance;
id <AppiraterDelegate> delegate = self.sharedInstance.delegate;
if ([delegate respondsToSelector:@selector(appiraterWillPresentModalView:animated:)]) {
[delegate appiraterWillPresentModalView:self.sharedInstance animated:_usesAnimation];
}
[[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.
} else {
#if TARGET_IPHONE_SIMULATOR
NSLog(@"APPIRATER NOTE: iTunes App Store is not supported on the iOS simulator. Unable to open App Store page.");
#else
NSString *reviewURL = [templateReviewURL stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]];
// iOS 7 needs a different templateReviewURL @see https://github.com/arashpayan/appirater/issues/131
// Fixes condition @see https://github.com/arashpayan/appirater/issues/205
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 && [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0) {
reviewURL = [templateReviewURLiOS7 stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]];
}
// iOS 8 needs a different templateReviewURL also @see https://github.com/arashpayan/appirater/issues/182
else if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 8.0)
{
reviewURL = [templateReviewURLiOS8 stringByReplacingOccurrencesOfString:@"APP_ID" withString:[NSString stringWithFormat:@"%@", _appId]];
}
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:reviewURL]];
#endif
}
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
id <AppiraterDelegate> 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;
}
}
//Delegate call from the StoreKit view.
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
[Appirater closeModal];
}
//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];
// get the top most controller (= the StoreKit Controller) and dismiss it
UIViewController *presentingController = [UIApplication sharedApplication].keyWindow.rootViewController;
presentingController = [self topMostViewController: presentingController];
[presentingController dismissViewControllerAnimated:_usesAnimation completion:^{
id <AppiraterDelegate> delegate = self.sharedInstance.delegate;
if ([delegate respondsToSelector:@selector(appiraterDidDismissModalView:animated:)]) {
[delegate appiraterDidDismissModalView:(Appirater *)self animated:usedAnimation];
}
}];
[self.class setStatusBarStyle:(UIStatusBarStyle)nil];
}
}
@end

View file

@ -1,23 +0,0 @@
//
// AppiraterDelegate.h
// Banana Stand
//
// Created by Robert Haining on 9/25/12.
// Copyright (c) 2012 News.me. All rights reserved.
//
#import <Foundation/Foundation.h>
@class Appirater;
@protocol AppiraterDelegate <NSObject>
@optional
-(BOOL)appiraterShouldDisplayAlert:(Appirater *)appirater;
-(void)appiraterDidDisplayAlert:(Appirater *)appirater;
-(void)appiraterDidDeclineToRate:(Appirater *)appirater;
-(void)appiraterDidOptToRate:(Appirater *)appirater;
-(void)appiraterDidOptToRemindLater:(Appirater *)appirater;
-(void)appiraterWillPresentModalView:(Appirater *)appirater animated:(BOOL)animated;
-(void)appiraterDidDismissModalView:(Appirater *)appirater animated:(BOOL)animated;
@end

View file

@ -15,7 +15,6 @@ iphone_lib = [
'game_center.mm', 'game_center.mm',
'in_app_store.mm', 'in_app_store.mm',
'icloud.mm', 'icloud.mm',
#'Appirater.m',
'ios.mm', 'ios.mm',
] ]
@ -30,10 +29,6 @@ if env['ios_gles22_override'] == "yes":
env_ios.Append(CPPFLAGS=['-DGLES2_OVERRIDE']) env_ios.Append(CPPFLAGS=['-DGLES2_OVERRIDE'])
# if env['ios_appirater'] == "yes":
# env_ios.Append(CPPFLAGS=['-DAPPIRATER_ENABLED'])
obj = env_ios.Object('godot_iphone.cpp') obj = env_ios.Object('godot_iphone.cpp')
prog = None prog = None

View file

@ -52,10 +52,6 @@
#define kRenderingFrequency 60 #define kRenderingFrequency 60
#define kAccelerometerFrequency 100.0 // Hz #define kAccelerometerFrequency 100.0 // Hz
#ifdef APPIRATER_ENABLED
#import "Appirater.h"
#endif
Error _shell_open(String); Error _shell_open(String);
void _set_keep_screen_on(bool p_enabled); void _set_keep_screen_on(bool p_enabled);
@ -188,11 +184,6 @@ static int frame_count = 0;
Main::start(); Main::start();
++frame_count; ++frame_count;
#ifdef APPIRATER_ENABLED
int aid = GlobalConfig::get_singleton()->get("ios/app_id");
[Appirater appLaunched:YES app_id:aid];
#endif
}; break; // no fallthrough }; break; // no fallthrough
default: { default: {

View file

@ -30,7 +30,6 @@ def get_opts():
('store_kit', 'Support for in-app store', 'yes'), ('store_kit', 'Support for in-app store', 'yes'),
('icloud', 'Support for iCloud', 'yes'), ('icloud', 'Support for iCloud', 'yes'),
('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'), ('ios_gles22_override', 'Force GLES2.0 on iOS', 'yes'),
('ios_appirater', 'Enable Appirater', 'no'),
('ios_exceptions', 'Use exceptions when compiling on playbook', 'yes'), ('ios_exceptions', 'Use exceptions when compiling on playbook', 'yes'),
('ios_triple', 'Triple for ios toolchain', ''), ('ios_triple', 'Triple for ios toolchain', ''),
('ios_sim', 'Build simulator binary', 'no'), ('ios_sim', 'Build simulator binary', 'no'),