0

I am new to the settings of notification permission granting and checking, I implemented permission granting if I checked the setting is denied or not determined, my code seems not to work, it didn't have an error but it just did not shows the window for asking for the grant of permission:

import UIKit
import UserNotifications
import Alamofire
import SwiftyJSON

class HomePageViewController: UIViewController {


    @IBOutlet weak var userName: UILabel!
    
    let content = UNMutableNotificationContent()

    
    override func viewDidLoad() {
        super.viewDidLoad()
        // notification create:
        userName.text = "Welcome! \(MyVariables.username)"
        let center = UNUserNotificationCenter.current()
        
        center.getNotificationSettings(completionHandler: { settings in
            if(settings.authorizationStatus == .denied || settings.authorizationStatus == .notDetermined){
                print("not granted or denied")
                center.requestAuthorization(options: [.alert, .sound])
                    {(granted, error) in
                }
            }
        })
        getRequest()
        // Do any additional setup after loading the view.
    }
    
    // the function that get Request from the API
    func getRequest(){
        
        let params: [String:Any] = ["username": MyVariables.username]
        // print(MyVariables.username)
        AF.request("url", method: .post, parameters: params, encoding: JSONEncoding.default)
                    .responseJSON { (response) in
                        do{
                            print(String(data: response.data!, encoding: .utf8))
                            let json = try JSON(data: response.data!)
                            var flag: Bool = false
                            var countor: Int = 1
                            // if it has trigger pulling:
                            var info:String = ""
                            
                            while json[String(countor)]["message"].stringValue != ""{
                                print("reached")
                                flag = true
                                info += json[String(countor)]["message"].stringValue
                                if(json[String(countor + 1)]["message"].stringValue != ""){
                                    countor += 1
                                    info += "\n"
                                } else {
                                    break
                                }
                                
                            }
                            if(flag){
                                let center = UNUserNotificationCenter.current()
                                self.content.title = "Trigger(s) pulled"
                                self.content.body = info
                                self.content.sound = UNNotificationSound.default
                                let uuidString = UUID().uuidString
                                let request = UNNotificationRequest(identifier: uuidString, content: self.content, trigger: nil)
                                center.add(request) { (error) in
                                    print(error ?? "")
                                }
                                // send alert window:
                                self.createAlert(title: " trigger(s) pulled",
                                                 message: "You have \(countor) triggers pulled: \n \(info)")
                                // reinitialize flag back to false
                                flag = false
                            }
                            // notification
//                            if(1 == 0){
//                                self.createAlert(title: " ", message: "The triger pulled")
//                            }
                        } catch let jsonErr{
                            print(jsonErr)
                        }
                        
                        // Trigger a new request 5s after the response
                        DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: { [weak self] in
                            self?.getRequest()
                        })
                    }
    }
    
    func createAlert(title: String, message: String){
        let Alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
        Alert.addAction(UIAlertAction(title: "ok", style: UIAlertAction.Style.default, handler: { (action) in
            Alert.dismiss(animated: true, completion: nil)
        }))
        self.present(Alert, animated: true, completion: nil)
    }
    

    /*
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */

}

In the testing cases, I turned off the notification in the setting of the anmulator

This is how my console looks:

not granted or denied
nil
Optional("{}\n")

which means I checked that the permission is not granted but I didn't see any window and the error message seems nil and the last one is the execution of getRequest()

One more question, as shown on code, if I need to use the center variable to push the notification request in getRequest(), is it fine that I declare another one in getRequest() except for one in the viewDidload()? Or should I have the global variable in the class outside these methods and call them by self.center?

matt
  • 515,959
  • 87
  • 875
  • 1,141
siiulan
  • 55
  • 6
  • If notification permissions have been explicitly denied by the user then the permissions prompt will not be displayed. The permissions prompt is only displayed where the user has not made a choice (permitted or denied). Once the prompt is shown and the user has made a choice, the permissions can only be modified by the user going into settings. The app doesn't get another chance to ask for permissions – Paulw11 Nov 11 '20 at 22:22

1 Answers1

1

From documentation:

The first time your app makes this authorization request, the system prompts the user to grant or deny the request and records the user’s response. Subsequent authorization requests don’t prompt the user. Blockquote

So basically you are trying to request permissions when they were already denied:

if(settings.authorizationStatus == .denied || settings.authorizationStatus == .notDetermined){
    print("not granted or denied")
    center.requestAuthorization(options: [.alert, .sound]){ (granted, error) in
    }
}

You can't. You can only ask for permissions if authorizationStatus is .notDetermined. This answer describes the best strategy:

let current = UNUserNotificationCenter.current()

current.getNotificationSettings(completionHandler: { (settings) in

    if settings.authorizationStatus == .notDetermined {

        print("not granted yet - ask the user")
        center.requestAuthorization(options: [.alert, .sound]){ (granted, error) in
             guard error == nil && granted else {
                  print("User denied permissions, or error occurred")
                  return
             }
             print("permissions granted")
        }
    } else if settings.authorizationStatus == .denied {
        print("Notification permission was previously denied, tell the user to go to settings & privacy to re-enable")
    } else if settings.authorizationStatus == .authorized {
        print("Notification permission was already granted")
    }
})

If you want to retest .notDetermined state after permissions were granted or denied, you need to uninstall the app.

timbre timbre
  • 12,648
  • 10
  • 46
  • 77