我知道之前已经有人问过这个问题,但是我想弄清楚我的项目存在的问题,因为标题(a)试图在(a)上提出,我已经检查了所有segue触发器,看看是否意外设置了segue转到已经打开的同一个视图控制器,但事实并非如此。

查看控制器1代码

import UIKit
import UserNotifications

class NotificationViewController: UIViewController {

    let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications

    let current = UNUserNotificationCenter.current()

    @IBAction func Notification(_ sender: Any) {

        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge], completionHandler: {didAllow, error in})

        var i = 0

        while i < 1{

        current.getNotificationSettings(completionHandler: { (settings) in
            if settings.authorizationStatus == .notDetermined {
                // Notification permission has not been asked yet, go for it!
            }

            if settings.authorizationStatus == .denied {
                i = i + 1
                DispatchQueue.main.async {
                    self.performSegue(withIdentifier: "ToLocation", sender: self)
                    // Notification permission was previously denied, go to settings & privacy to re-enable
                }

            }

            if settings.authorizationStatus == .authorized {
                i = i + 1
                DispatchQueue.main.async {
                 self.performSegue(withIdentifier: "ToLocation", sender: self)
                    // Notification permission was already granted
                }

            }
        })
        }

        }

    override func viewDidLoad() {

        current.getNotificationSettings(completionHandler: { (settings) in
            if settings.authorizationStatus == .notDetermined {
                // Notification permission has not been asked yet, go for it!
            }

            if settings.authorizationStatus == .denied {
                DispatchQueue.main.async {
                    self.performSegue(withIdentifier: "ToLocation", sender: self)
                    // Notification permission was previously denied, go to settings & privacy to re-enable
                }

            }

            if settings.authorizationStatus == .authorized {
                DispatchQueue.main.async {
                    self.performSegue(withIdentifier: "ToLocation", sender: self)
                    // Notification permission was already granted
                }

            }
        })

        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}


查看控制器2代码

    import UIKit
import CoreLocation

class LocationViewController: UIViewController {

    @IBOutlet weak var textview: UITextView!

    let locationManager = CLLocationManager()

    @IBAction func OnLocation(_ sender: Any) {

        locationManager.delegate = self as? CLLocationManagerDelegate

        var i = 0

        while i < 1{

            switch CLLocationManager.authorizationStatus() {
            case .notDetermined:
                // Request when-in-use authorization initially
                locationManager.requestWhenInUseAuthorization()
                break

            case .restricted, .denied:
                i = i + 1
                DispatchQueue.main.async {
                    self.performSegue(withIdentifier: "ToLogin", sender: self)
                }
                // Disable location features
                //disableMyLocationBasedFeatures()
                break

            case .authorizedWhenInUse:
                i = i + 1
                DispatchQueue.main.async {
                    self.performSegue(withIdentifier: "ToLogin", sender: self)
                }
                // Enable basic location features
                //enableMyWhenInUseFeatures()
                break

            case .authorizedAlways:
                // Enable any of your app's location features
               // enableMyAlwaysFeatures()
                break
            }
        }
    }


    override func viewDidLoad() {
        func locationManager(_ manager: CLLocationManager,
                             didChangeAuthorization status: CLAuthorizationStatus) {   switch status {

        case .restricted, .denied:
            self.performSegue(withIdentifier: "ToLogin", sender: self)
            break

        case .authorizedWhenInUse:
            self.performSegue(withIdentifier: "ToLogin", sender: self)
            break

        case .authorizedAlways:
            self.performSegue(withIdentifier: "ToLogin", sender: self)
            break

        case .notDetermined:
            break
            }
        }
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}


错误信息


  018-02-27 23:06:41.534749 + 1030请求[27358:1351259]警告:尝试
  呈现
   在演讲时
  正在处理!

最佳答案

不不不不不是这样的抱歉,UNUserNotification的requestAuthorization方法的completeHandler结果参数可能在后台线程上执行。

此功能的提示

@IBAction func Notification(_ sender: Any)


*应以小写字母开头

*提供一个名称,该名称可以推断出它完成的动作

*更改发送者的类型(如果知道的话),这样就可以显式调用该对象的属性或方法而无需强制转换。

在函数范围内继续执行其余代码。 requestAuthorization对此负有唯一责任-请求权限-响应为didAllow或错误。您从不检查它,并继续启动另一个响应也是另一个线程的块

最重要的是:您的调用requestAuthorization和getNotificationSettings在一个循环内(为什么?),如果此代码在30%的时间内执行,您会很幸运。

因此,您应该分离一些涉及权限的代码,阅读有关GRASP原理的几行内容,还阅读每一章here

07-27 19:03