Is there a way to check app has ever acquired push notification permission by system alert?
UIApplication.sharedApplication().currentUserNotificationSettings()?.types.rawValue
It returns 0 both when app never requested push notification permission and when user declined permission.
I want to show the system alert popup when app never requested permission. Also I want to let user go to setting to control permission setting if user ever declined permission.
For example:
let pushNotificationPermissionNeverAcquired: Bool = ???
if (pushNotificationPermissionNeverAcquired) {
// show system popup to acquire push notification permission
UIApplication.sharedApplication.registerForRemoteNotificationTypes([ * some types ])
} else if (UIApplication.sharedApplication().currentUserNotificationSettings()?.types.rawValue == 0) {
// user declined push notification permission, so let user go to setting and change the permission
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString))
} else {
// push notification is allowed
}
How can I check pushNotificationPermissionNeverAcquired?
This is how I am doing it right now.
if NSUserDefaults.standardUserDefaults().stringForKey(NOTIFICATION_PERMISSIONS_ASKED) == nil
{
NSUserDefaults.standardUserDefaults().setObject("true", forKey: NOTIFICATION_PERMISSIONS_ASKED)
// Request permissions
}
else
{
// Show your own alert
}
You could save a Boolean too if you want and access it with 'boolForKey', it returns false if no key was found.
Forgot this as well.
if let enabledTypes = UIApplication.sharedApplication().currentUserNotificationSettings()?.types {
switch enabledTypes
{
case UIUserNotificationType.None:
// Denied permissions or never given
default:
// Accepted
}
}
Related
I'd like to have the history section of an app locked for everyone besides the person who owns the phone. I don't like forcing the user to make an account or make a new PIN just for this app. Can I authorize using the PIN, Face ID or Touch ID he has already set up?
The Local Authentication framework will handle this.
Here is part of an Apple code sample:
/// Logs out or attempts to log in when the user taps the button.
#IBAction func tapButton(_ sender: UIButton) {
if state == .loggedin {
// Log out immediately.
state = .loggedout
} else {
// Get a fresh context for each login. If you use the same context on multiple attempts
// (by commenting out the next line), then a previously successful authentication
// causes the next policy evaluation to succeed without testing biometry again.
// That's usually not what you want.
context = LAContext()
context.localizedCancelTitle = "Enter Username/Password"
// First check if we have the needed hardware support.
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
let reason = "Log in to your account"
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason ) { success, error in
if success {
// Move to the main thread because a state update triggers UI changes.
DispatchQueue.main.async { [unowned self] in
self.state = .loggedin
}
} else {
print(error?.localizedDescription ?? "Failed to authenticate")
// Fall back to a asking for username and password.
// ...
}
}
} else {
print(error?.localizedDescription ?? "Can't evaluate policy")
// Fall back to a asking for username and password.
// ...
}
}
}
When using Apple login, I want to know how to log out. Two revoking methods I know
[1] Upon opening your app
Open the Settings app, then tap [your name].
Tap Password & Security
Tap Apps Using Your Apple ID.
let authorizationAppleIDProvider = ASAuthorizationAppleIDProvider()
authorizationAppleIDProvider.getCredentialState(forUserID: "currentUserIdentifier") { (credentialState: ASAuthorizationAppleIDProvider.CredentialState, error: Error?) in
if let error = error {
print(error)
// Something went wrong check error state
return
}
switch (credentialState) {
case .authorized:
//User is authorized to continue using your app
break
case .revoked:
//User has revoked access to your app
break
case .notFound:
//User is not found, meaning that the user never signed in through Apple ID
break
default: break
}
}
How to know through this code when running the app afterwards
[2] While your app is running
let notificationCenter = NotificationCenter.default
let sessionNotificationName = NSNotification.Name.ASAuthorizationAppleIDProviderCredentialRevoked
appleIDSessionObserver = notificationCenter.addObserver(forName: sessionNotificationName, object: nil, queue: nil) { (notification: Notification) in
//Sign user out
}
This code notifies when a credentialState becomes revoked when a user session changes.
What I'm curious about is [2] While your app is running, in what situation is the user session revoked in the app? For example, if you press the logout button, credentialState becomes revoked, you will receive notifications and execute the logout function, right? How to revoked appleId CredentialState in the context of using the app?
How I can check is the Face ID is Enabled/ Disabled in settings page?
I checked in LAContext error type. It return
Code=-6 "User has denied the use of biometry for this app."
But the device do not support biometric authentication also getting same error code. (kLAErrorTouchIDNotAvailable -6)
Is any way to find user enabled/disabled Face ID in settings?
first add a method for your users to enable faceid/Touch ID using local authentication. adding this method will allow users to enable and disable biometric id in settings. you can use a whatever method you'd like, button, segment controller or view and using a prompt you'll ask the users permission to enable biometric id. This code may help:
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Enable FaceID!"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) {
[unowned self] (success, authenticationError) in
DispatchQueue.main.async {
if success {
self.unlockSecretMessage()
} else {
// error
}
}
}
} else {
// no biometry
}
I need to reload the music list in my app when the user allows the access to media library, and I would like to show a notification when the user disallows the access. How can I get the two callbacks?
For requesting access, I just added this line into the info.plist NSAppleMusicUsageDescription
You need to ask for the permission for accessing MPMediaLibrary, this is how you can request for it
Objective-C
[MPMediaLibrary requestAuthorization:^(MPMediaLibraryAuthorizationStatus authorizationStatus) {
if ( authorizationStatus == MPMediaLibraryAuthorizationStatusAuthorized ) {
// Reload your list here
} else {
// user did not authorize
} }];
Swift
MPMediaLibrary.requestAuthorization { (status) in
if status == .authorized {
// Reload your list here
} else {
// user did not authorize
}
}
As of iOS8 you to need to register and prompt the user for the use of Local Notifications. Therefore I'd like to implement a way to double check these permissions.
How can I check for the case of Local Notifications settings being not determined/not set yet? So far I only know how to check for Local Notifications being granted or denied, like this …
var currentStatus = UIApplication.sharedApplication().currentUserNotificationSettings()
var requiredStatus:UIUserNotificationType = UIUserNotificationType.Alert
if currentStatus.types == requiredStatus {
… //GRANTED
} else {
… //DENIED
}
The problem using this is I also get a Denied if there is nothing set so far. How can I differentiate all 3 cases?
Granted (Notification, Alert Type)
Denied (Notification, Alert Type)
Undefined/Not set yet (therefore local notification app settings not created yet)
As an alternative solution it would be helpful to have a comparable delegate method to CoreLocation's authorization didChangeAuthorizationStatus in order to react on the user's selection on the permissions alert. Is there something like this in order to get the state of user interaction with the privacy alert for local notifications?
The solution I implemented :
In app delegate, I detect when didRegisterUserNotificationSettings is shot. And I save in userdefaults a bool to true :
func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
NSUserDefaults.standardUserDefaults().setBool(true, forKey: "notificationsDeterminedKey")
NSUserDefaults.standardUserDefaults().synchronize()
}
And when I need to know the status :
if NSUserDefaults.standardUserDefaults().boolForKey("notificationsDeterminedKey") {
let grantedSettings = UIApplication.sharedApplication().currentUserNotificationSettings()
if grantedSettings.types == UIUserNotificationType.None {
// Denied
} else {
// Granted
} else {
// Not Determined
}
I just found an appropriate UIApplication delegate method that helps to solve this:
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:
(UIUserNotificationSettings *)notificationSettings {
You can find more details on this in WWDC14 Session 713 "What’s New in iOS Notifications".