SKStoreReviewController is being displayed the first time user launches the app - ios

In my iOS app I'm using SKStoreReviewController to request users to rate the app. The Apple documentation says to put the code for requesting the "Rate Us" popup anywhere we want, and they will govern when it will be actually displayed.
I wrote the following code in the first view of the app:
func requestReview() {
SKStoreReviewController.requestReview()
}
The problem is that the popup is displayed to my app's users as soon as they first launch the app, which makes no sense. Is there any way to control the popup's appearance and avoid showing it before certain amount of uses of the app?

SKStoreReviewController.requestReview() will display the popup for the first few times (to be exact, for the first 3 times in a year).
Create a variable that you increment each time in your application delegate's didFinishLaunchingWithOptions method and save it to UserDefaults. After that, you can check whether a user opened the app enough times.
AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
var appLaunches = UserDefaults.standard.integer(forKey: "appLaunches")
appLaunches += 1
UserDefaults.standard.set(appLaunches, forKey: "appLaunches")
return true
}
The view controller where you want to display the store review controller
let appLaunches = UserDefaults.standard.integer(forKey: "appLaunches")
if appLaunches >= [enough number of app launches] {
SKStoreReviewController.requestReview()
}

Related

Force touch the app icon when app closed from task manager

while using quick actions of 3D Touch it works good but while app is terminated first time force touch the app icon it open home screen but the other times it open the right screen.
why this happen and how I can test the app while it is terminated
From the method application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) you can use the launchOptions argument to detect whether user is launching the app by pressing shortcut item key or not.
if launchOptions != nil {
if let userInfo = launchOptions![UIApplicationLaunchOptionsShortcutItemKey] {
//Handled the implementation here
}
}

How do you save global arrays in the applicationWillTerminate and reload them in the application function?

So I have been trying to make an app for my Mobile Apps Development class and I need to find a solution to a problem that I'm having when I save a global array called "events".
Here I tried to reload the saved event class in AppDelegate but it didn't change in the main screen view controller:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
//Override point for customization after application launch.
//Load the events that were saved when application was terminated
let eventKey = NSUserDefaults.standardUserDefaults()
Global.events = (eventKey.arrayForKey("savedEvents") as? [Event])!
return true
}
Here is the function that is called when someone quits the app:
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
let myEvents = Global.events
NSUserDefaults.standardUserDefaults().setObject(myEvents, forKey: "savedEvents")
NSUserDefaults.standardUserDefaults().synchronize()
}
This might just be an error in the viewcontroller that displays this array but if you see something wrong with the code please let me know.
Two problems:
In iOS, there is no such thing as "someone quits the app", and thus what you're doing is unlikely to work, because applicationWillTerminate is never called. Save when the application is deactivated or backgrounded.
An array of Event cannot magically be saved in user defaults, because Event is not a Property List type. You will need to make Event archivable and archive the array.

CLCircularRegion and wake up app

In application we have mechanism like native Reminder app in iOS with firing notifications when user enter or exit in some region.
But two devices behave differently (5 and 5s) in same time. All devices have enable notifications, and allow use locations.
Two devices have a some "travel" and in the route created 10 points. First device (5) when came to finish received only 6 notifications, (5s) don't receive any notification.
But my question is how I can know when my app is restart in background or continue working. Because, all log in app I redirect into a file, and after download container and analyze what happened in app in travel time.
I noticed app restart in same times when device is enter to region and my log marks fired in the file but notifications don't receive. This is happended when app try to get some information from web service in didFinishLaunchingWithOptions
And maybe this is problem. How to know distinguish restart app or continue working. Thx.
Are you checking UIApplicationLaunchOptionsLocationKey in didFinishLaunchingWithOptions similar to (sorry, Swift is what I have now):
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
if launchOptions?[UIApplicationLaunchOptionsLocationKey] != nil {
// app was launched in response to incoming location event
}
}
Additionally, if you're not already doing this you may need to create notifications differently if app is in background:
// Show an alert if application is active
if UIApplication.sharedApplication().applicationState == .Active {
if let message = notefromRegionIdentifier(region.identifier) {
if let viewController = window?.rootViewController {
showSimpleAlertWithTitle(nil, message: message, viewController: viewController)
}
}
}
else {
// Otherwise present a local notification:
let notification = UILocalNotification()
notification.alertBody = notefromRegionIdentifier(region.identifier)
notification.soundName = "Default";
UIApplication.sharedApplication().presentLocalNotificationNow(notification)
}

Check if iOS push notifications status is not determined

I’m prompting my user to enable push notifications after the user logs in to my app. I know how to test if push notifications are enabled or disabled using:
isRegisteredForRemoteNotifications
and it works just fine. It returns YES for enabled and NO for not available but I want to be able to figure out how to check for Not Determined (the user wasn’t prompted to enable push notifications to begin with). Is there a way to test that?
Thanks in advance!
You create Not Determined state yourself.
func registerNotification() {
// 1.Call register API
// ...
// 2.Save a bool value to indicate you've called this method or not.
let appleSuggestedUserDefaultsKeyPrefix = "com.yourcompany.product-"
let key = appleSuggestedUserDefaultsKeyPrefix + "didCallRegisterNotificationAPI"
NSUserDefaults.standardUserDefaults().setBool(true, forKey: key)
}
And in didFinishLaunchingWithOptions method you need check if you have called registerNotification().
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
let didCallRegisterNotificationAPI = NSUserDefaults.standardUserDefaults().boolForKey(...)
if didCallRegisterNotificationAPI {
// If registered or user denied, call this method will NOT show the alert.
// Just the same as you did before.
registerNotification()
} else {
print("registerNotification() has not been called")
}
}
And finally you can call registerNotification() directly anywhere anytime as you need and the alert is under your control now.
isRegisteredForRemoteNotifications is a Bool. There is no undetermined status. You can verify this is the reference.
When the user first installs your app they must either allow or disallow push notifications. There is no other possible option.
However, maybe you're asking because you can delete the app, reinstall, and it won't ask you for permission. That's because the permission is remembered.
Resetting the Push Notifications Permissions Alert on iOS
The first time a push-enabled app registers for push notifications, iOS asks the user if they wish to receive notifications for that app. Once the user has responded to this alert it is not presented again unless the device is restored or the app has been uninstalled for at least a day.
If you want to simulate a first-time run of your app, you can leave the app uninstalled for a day. You can achieve the latter without actually waiting a day by following these steps:
Delete your app from the device.
Turn the device off completely and turn it back on.
Go to Settings > General > Date & Time and set the date ahead a day or more.
Turn the device off completely again and turn it back on.
Reference
Associated Question: When I delete my iOS application push notification state remains
EDIT:
You can only use isRegisteredForRemoteNotifications to check that they are simply not registered, whether that's due to declining or due to you never trying to register.
However, as long as you try to register in a valid way (valid certs and profiles etc) and the user declines, your app will call did register, but with nil UIUserNotificationSettings:
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
if notificationSettings.types == nil {
println("You didn't allow notifcations")
}
}
You can make use of UNNotificationSettings's authorizationStatus property.
private func checkNotificationsAuthorizationStatus() {
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.getNotificationSettings { notificationSettings in
switch notificationSettings.authorizationStatus {
case .authorized:
print("Authorized to schedule or receive notifications.")
case .denied:
print("Not authorized to schedule or receive notifications.")
case .notDetermined:
print("Not determined whether the app is allowed to schedule notifications.")
case .provisional: // Available from iOS 12.0
print("Provisionally authorized to post noninterruptive user notifications.")
#unknown default:
print("Error")
}
}
}
Use it in didFinishLaunchingWithOptions like:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.registerForRemoteNotifications()
self.checkNotificationsAuthorizationStatus()
return true
}

Parse Seamless Login

I have created an app using parse with Swift , when a user opens the app (not from the background) the login screen shows for a split second before moving to the main view. I wan't it to go straight to the main screen if the user is logged in.
I have tried putting the following code nearly everywhere.
if PFUser.currentUser() != nil {
}
I tried NSUserDefaults to check if the user is logged in, in the app delegate didFinishLaunching, couldn't get it to work.
Any help would be greatly appreciated , thanks.
You need to put the check into your "AppDelegate.swift" file.
Then depending on if the user is logged in or not load the MAIN viewcontroller or the LOGIN viewcontroller.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Other stuff you need to setup the app...
if PFUser.currentUser() == nil
{
//Load the Login ViewController
}
else
{
//Load the Main ViewController
}
return true
}

Resources