NSNotification:尝试在视图不在 window 层次结构中的 ViewController 上呈现 UIAlertController
NSNotification: Attempt to present UIAlertController on ViewController whose view is not in the window hierarchy
我试图在我的 ViewController 中通过 NSNotification 调用的函数中显示 UIAlertController。但是我收到错误:
Attempt to present <UIAlertController: 0x7fe013d05d40> on <submarine.ViewController: 0x7fe011f20370> whose view is not in the window hierarchy!
NSNotification 是从我的 UI 中的其他内容的完成块(我猜是回调)发布的。因为它是一个回调,所以无法显示。因此我想我会尝试 NSNotificationCentre 来解决这个问题而不使用 rootViewController 来显示警报。
我的代码是:
override func viewDidAppear(animated: Bool) {
// Handle onboarding
if needsOnboarding() {
handleOnboarding() // This create the completion block that posts the NSNotification
}
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showTermsAlert:", name:"showTermsAlert", object: nil)
}
func showTermsAlert(notification: NSNotification) {
let termsAlert:UIAlertController = UIAlertController(title: "Terms And Conditions", message: "Please view the terms below before accepting them.", preferredStyle: UIAlertControllerStyle.Alert)
termsAlert.addAction(UIAlertAction(title: "View Terms", style: .Default, handler: { (action: UIAlertAction!) in
UIApplication.sharedApplication().openURL(NSURL(string: "my_terms_url")!)
}))
termsAlert.addAction(UIAlertAction(title: "I Agree to the Terms", style: .Default, handler: { (action: UIAlertAction!) in
self.onboardingFinished()
}))
self.presentViewController(termsAlert, animated: true, completion: nil)
}
有没有人知道为什么会这样?我不明白为什么它不在 window 层次结构中 - 它是从 self
viewController 中呈现的,并且是在 VC 中的顶级函数中创建的。
谢谢!
编辑:handleOnboarding()
:
中的原始代码
使用的库:Onboard
func handleOnboarding() {
let secondPage = OnboardingContentViewController(title: "What's going on?", body: "Submarine routes your data through our network, around any filters and restrictions, giving you unrestricted and unmonitored internet access.", image: UIImage(named: "back"), buttonText: "Next") { () -> Void in
// do something here when users press the button, like ask for location services permissions, register for push notifications, connect to social media, or finish the onboarding process
}
secondPage.movesToNextViewController = true
let thirdPage = OnboardingContentViewController(title: "Terms of Use", body: "You must agree to our Terms of Use to use Submarine.\nIf you don't, please close Submarine.", image: UIImage(named: "back"), buttonText: "View Terms") { () -> Void in
let termsAlert:UIAlertController = UIAlertController(title: "Terms And Conditions", message: "Please view the terms below before accepting them.", preferredStyle: UIAlertControllerStyle.Alert)
termsAlert.addAction(UIAlertAction(title: "View Terms", style: .Default, handler: { (action: UIAlertAction!) in
UIApplication.sharedApplication().openURL(NSURL(string: "my_policy_url")!)
}))
termsAlert.addAction(UIAlertAction(title: "I Agree to the Terms", style: .Default, handler: { (action: UIAlertAction!) in
self.onboardingFinished()
}))
self.presentViewController(termsAlert, animated: true, completion: nil)
// NSNotificationCenter.defaultCenter().postNotificationName("showTermsAlert", object: nil)
}
// Image
let onboardingVC = OnboardingViewController(backgroundImage: UIImage(named: "back"), contents: [secondPage, thirdPage])
self.navigationController?.presentViewController(onboardingVC, animated: false, completion: nil)
}
当呈现视图控制器不再是控制器层次结构的一部分,并且它的视图不再位于任何 window 的视图层次结构中时,就会发生这种情况。最有可能的是,控制器被关闭或弹出,但它听到了通知并尝试显示警报控制器。
您应该更仔细地管理您的控制器状态。当控制器从您的控制器层次结构中被解雇或弹出时,可能会删除观察者。
我想对您的代码进行一些更改。在 viewDidAppear:
中添加对 super 的调用,并停止使用 NSNotification
进行演示。您不知道使用此模式将调用哪个线程 showTermsAlert
。您可以通过直接调用 showTermsAlert
使您的意图更加明确,这也将保证您在主线程上。
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// Handle onboarding
if needsOnboarding() {
self.showTermsAlert()
}
}
func showTermsAlert() {
let termsAlert:UIAlertController = UIAlertController(title: "Terms And Conditions", message: "Please view the terms below before accepting them.", preferredStyle: UIAlertControllerStyle.Alert)
termsAlert.addAction(UIAlertAction(title: "View Terms", style: .Default, handler: { (action: UIAlertAction!) in
UIApplication.sharedApplication().openURL(NSURL(string: "my_terms_url")!)
}))
termsAlert.addAction(UIAlertAction(title: "I Agree to the Terms", style: .Default, handler: { (action: UIAlertAction!) in
self.onboardingFinished()
}))
self.presentViewController(termsAlert, animated: true, completion: nil)
}
我试图在我的 ViewController 中通过 NSNotification 调用的函数中显示 UIAlertController。但是我收到错误:
Attempt to present <UIAlertController: 0x7fe013d05d40> on <submarine.ViewController: 0x7fe011f20370> whose view is not in the window hierarchy!
NSNotification 是从我的 UI 中的其他内容的完成块(我猜是回调)发布的。因为它是一个回调,所以无法显示。因此我想我会尝试 NSNotificationCentre 来解决这个问题而不使用 rootViewController 来显示警报。
我的代码是:
override func viewDidAppear(animated: Bool) {
// Handle onboarding
if needsOnboarding() {
handleOnboarding() // This create the completion block that posts the NSNotification
}
NSNotificationCenter.defaultCenter().addObserver(self, selector: "showTermsAlert:", name:"showTermsAlert", object: nil)
}
func showTermsAlert(notification: NSNotification) {
let termsAlert:UIAlertController = UIAlertController(title: "Terms And Conditions", message: "Please view the terms below before accepting them.", preferredStyle: UIAlertControllerStyle.Alert)
termsAlert.addAction(UIAlertAction(title: "View Terms", style: .Default, handler: { (action: UIAlertAction!) in
UIApplication.sharedApplication().openURL(NSURL(string: "my_terms_url")!)
}))
termsAlert.addAction(UIAlertAction(title: "I Agree to the Terms", style: .Default, handler: { (action: UIAlertAction!) in
self.onboardingFinished()
}))
self.presentViewController(termsAlert, animated: true, completion: nil)
}
有没有人知道为什么会这样?我不明白为什么它不在 window 层次结构中 - 它是从 self
viewController 中呈现的,并且是在 VC 中的顶级函数中创建的。
谢谢!
编辑:handleOnboarding()
:
使用的库:Onboard
func handleOnboarding() {
let secondPage = OnboardingContentViewController(title: "What's going on?", body: "Submarine routes your data through our network, around any filters and restrictions, giving you unrestricted and unmonitored internet access.", image: UIImage(named: "back"), buttonText: "Next") { () -> Void in
// do something here when users press the button, like ask for location services permissions, register for push notifications, connect to social media, or finish the onboarding process
}
secondPage.movesToNextViewController = true
let thirdPage = OnboardingContentViewController(title: "Terms of Use", body: "You must agree to our Terms of Use to use Submarine.\nIf you don't, please close Submarine.", image: UIImage(named: "back"), buttonText: "View Terms") { () -> Void in
let termsAlert:UIAlertController = UIAlertController(title: "Terms And Conditions", message: "Please view the terms below before accepting them.", preferredStyle: UIAlertControllerStyle.Alert)
termsAlert.addAction(UIAlertAction(title: "View Terms", style: .Default, handler: { (action: UIAlertAction!) in
UIApplication.sharedApplication().openURL(NSURL(string: "my_policy_url")!)
}))
termsAlert.addAction(UIAlertAction(title: "I Agree to the Terms", style: .Default, handler: { (action: UIAlertAction!) in
self.onboardingFinished()
}))
self.presentViewController(termsAlert, animated: true, completion: nil)
// NSNotificationCenter.defaultCenter().postNotificationName("showTermsAlert", object: nil)
}
// Image
let onboardingVC = OnboardingViewController(backgroundImage: UIImage(named: "back"), contents: [secondPage, thirdPage])
self.navigationController?.presentViewController(onboardingVC, animated: false, completion: nil)
}
当呈现视图控制器不再是控制器层次结构的一部分,并且它的视图不再位于任何 window 的视图层次结构中时,就会发生这种情况。最有可能的是,控制器被关闭或弹出,但它听到了通知并尝试显示警报控制器。
您应该更仔细地管理您的控制器状态。当控制器从您的控制器层次结构中被解雇或弹出时,可能会删除观察者。
我想对您的代码进行一些更改。在 viewDidAppear:
中添加对 super 的调用,并停止使用 NSNotification
进行演示。您不知道使用此模式将调用哪个线程 showTermsAlert
。您可以通过直接调用 showTermsAlert
使您的意图更加明确,这也将保证您在主线程上。
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
// Handle onboarding
if needsOnboarding() {
self.showTermsAlert()
}
}
func showTermsAlert() {
let termsAlert:UIAlertController = UIAlertController(title: "Terms And Conditions", message: "Please view the terms below before accepting them.", preferredStyle: UIAlertControllerStyle.Alert)
termsAlert.addAction(UIAlertAction(title: "View Terms", style: .Default, handler: { (action: UIAlertAction!) in
UIApplication.sharedApplication().openURL(NSURL(string: "my_terms_url")!)
}))
termsAlert.addAction(UIAlertAction(title: "I Agree to the Terms", style: .Default, handler: { (action: UIAlertAction!) in
self.onboardingFinished()
}))
self.presentViewController(termsAlert, animated: true, completion: nil)
}