在 UITabBarController 的当前上下文中呈现模态视图控制器后出现黑屏
Black screen after presenting modal view controller in current context from UITabBarController
我的根视图控制器是一个 UITabBarController。我正在尝试在选项卡栏控制器的视图控制器之一上呈现模态视图控制器,但仍然允许使用选项卡栏转到不同的选项卡 - 换句话说,我希望模态仅中断该特定选项卡的流程,而不是整个应用程序的流程。
为此,我在情节提要中将呈现视图控制器的呈现样式设置为 'Over Current Context'。我遇到的问题是,在呈现模态视图控制器并选择新选项卡后,呈现视图控制器的视图从 window 中删除,并且在关闭时不会添加回 window呈现的视图控制器。关闭视图控制器后,移动到另一个选项卡然后返回最终将呈现视图控制器放回 window。
我已经使用 Xcode 中的 'Tabbed' 模板重现了我的问题。
呈现模态后 - 我为呈现的视图控制器添加了透明度,以便轻松查看呈现的视图控制器中发生的事情。
切换到第二个选项卡然后返回 - 呈现视图控制器的视图现已删除。
关闭模态会使呈现视图控制器的视图仍然从 window 中移除。转到选项卡 2 并返回会将视图添加回 window。
我希望这是我在情节提要中忽略的简单事情,但事实上我可以在更改选项卡之前呈现模态并查看其背后呈现的视图控制器,这让我觉得我已经正确设置了东西。
我的选项卡控制器也有类似的问题,但是就像评论一样,我建议将转场更改为推送或显示转场。这将允许该选项卡在切换到其他选项卡时与显示的新视图保持一致,以代替旧视图。如果美学是一个问题,您可以制作一个自定义导航控制器来自定义新视图的外观。
我有同样的问题,并且能够通过在呈现模式 VC 之前在呈现视图控制器上设置 self.definesPresentationContext = YES;
来解决它。您也可以在故事板中设置它,该复选框在 Interface Builder 中称为 "Defines Context"。
我重现了您的问题并找到了解决方案。
它不涉及更改segue方法或更改故事板中的某些属性。
建议:
但在开始解决方案之前,我想补充一点,模态呈现的视图控制器的目的是扰乱应用程序的实际流程,并呈现一些额外的上下文信息或一些可操作的内容以呈现 vc。简而言之,这是非常合乎逻辑的,实际上建议在模态呈现视图控制器时覆盖选项卡栏。应用商店里有很多很好的例子。
话虽如此,这是我提出的解决方案。
解法:
我认为问题在于 UITabBarController 处理其视图层次结构的方式。
我所做的是在选项卡更改之前明确关闭模态呈现的视图控制器。这使得呈现视图控制器在选项卡栏切换到新选项卡之前一直存在于 UITabBarViewController 的视图层次结构中。
在模态呈现的 "viewWillDisappear" 方法中 ViewController 添加这个。
- (void)viewWillDisappear:(BOOL)animated {
[self dismissViewControllerAnimated:true completion:^{
[super viewWillDisappear:animated];
}];
}
我在当前的 swift 项目中遇到了同样的问题。我已经解决了这个问题。
然后我终于使用 NSNotificationCenter
并在更改选项卡时关闭该视图控制器以解决此问题。
我在 AppDelegate
中引用了标签栏控制器并在那里设置了委托。
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabbarcontroller = storyboard.instantiateViewControllerWithIdentifier("MyTabBarController") as! UITabBarController
tabbarcontroller.delegate = self
它的代表是
//MARK: - Tabbar controller delegate
extension AppDelegate : UITabBarControllerDelegate {
func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
NSNotificationCenter.defaultCenter().postNotificationName("TabBarTabChanged", object: nil)
}
}
然后我在呈现的视图控制器中添加了观察者
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PreviewPlaceVC.BackClickAction(_:)), name: "TabBarTabChanged", object: nil)
}
// MARK: - Button Click Actions
@IBAction func BackClickAction(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
它对我来说很好用。我认为在选项卡更改事件上关闭视图控制器不是一个合适的解决方案,但是关闭而不是黑屏是可以的,这也会破坏当时的导航。
尝试在应用程序 window 中呈现视图控制器。我有一个类似的问题,已通过以下代码解决:
let myNewVC = mainStoryBoard.instantiateViewController(withIdentifier: "MyNewVCId") as! MyNewVC
let navController = UINavigationController(rootViewController: myNewVC)
navController.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
let appDelegate = UIApplication.shared.delegate as? AppDelegate
appDelegate?.window?.rootViewController?.present(navController, animated: true, completion: nil)
希望这对你也有帮助。
iOS 10+ & Swift 3+
我已经很好地解决了这个问题。正在呈现视图控制器的全屏模态呈现样式。
let storyboard = UIStoryboard(name: "Main", bundle: nil) // Replace “Main” with your storyboard name
if let viewController = storyboard?.instantiateViewController(withIdentifier: “viewController Identifier”) as? ViewController {
viewController.modalPresentationStyle = .overFullScreen
self.present(viewController, animated: false, completion: {
})
}
Over full screen 会在你的标签栏(控制器)上覆盖你的视图控制器。因此,最终用户无法切换标签栏(除非您以编程方式执行操作)标签栏项目。用户必须关闭此视图控制器才能切换标签栏。
如果您正在使用 segue,则要呈现视图控制器然后 select 'Over Full Screen' 来自属性检查中的模态呈现样式
尝试在故事板中将您的演示文稿样式设置为 'Over Full Screen' 而不是 'Over Current Context'。
我遇到了这个问题:当我展示我的 ModalController 时它采用透明背景,当我将选项卡更改为 tabBarController 中的下一个选项卡并返回到上一个选项卡时,透明背景消失了并且研究后有一个糟糕的黑色背景我发现重点是:
self.definesPresentationContext = 真
self 不是模态控制器 self 是 modalController 的呈现控制器,另一点是 .overCurrentContext 像这样
self.definesPresentationContext = true
modalController.modalPresentationStyle = .overCurrentContext
self.present(modalController, animated: true, completion: nil)
在调用 ViewController!
之前,我还需要一个 Navigation Controller
并且我之前使用了描述的代码:
let newVC = self.storyboard?.instantiateViewController(withIdentifier: "newViewController")
self.definesPresentationContext = true
self.providesPresentationContextTransitionStyle = true
newVC?.modalPresentationStyle = .overCurrentContext //do NOT use .currentContext --> it will produce a black screen by switching over tabbar and close VC
self.present(newVC!, animated: false)
我的根视图控制器是一个 UITabBarController。我正在尝试在选项卡栏控制器的视图控制器之一上呈现模态视图控制器,但仍然允许使用选项卡栏转到不同的选项卡 - 换句话说,我希望模态仅中断该特定选项卡的流程,而不是整个应用程序的流程。
为此,我在情节提要中将呈现视图控制器的呈现样式设置为 'Over Current Context'。我遇到的问题是,在呈现模态视图控制器并选择新选项卡后,呈现视图控制器的视图从 window 中删除,并且在关闭时不会添加回 window呈现的视图控制器。关闭视图控制器后,移动到另一个选项卡然后返回最终将呈现视图控制器放回 window。
我已经使用 Xcode 中的 'Tabbed' 模板重现了我的问题。
呈现模态后 - 我为呈现的视图控制器添加了透明度,以便轻松查看呈现的视图控制器中发生的事情。
切换到第二个选项卡然后返回 - 呈现视图控制器的视图现已删除。
关闭模态会使呈现视图控制器的视图仍然从 window 中移除。转到选项卡 2 并返回会将视图添加回 window。
我希望这是我在情节提要中忽略的简单事情,但事实上我可以在更改选项卡之前呈现模态并查看其背后呈现的视图控制器,这让我觉得我已经正确设置了东西。
我的选项卡控制器也有类似的问题,但是就像评论一样,我建议将转场更改为推送或显示转场。这将允许该选项卡在切换到其他选项卡时与显示的新视图保持一致,以代替旧视图。如果美学是一个问题,您可以制作一个自定义导航控制器来自定义新视图的外观。
我有同样的问题,并且能够通过在呈现模式 VC 之前在呈现视图控制器上设置 self.definesPresentationContext = YES;
来解决它。您也可以在故事板中设置它,该复选框在 Interface Builder 中称为 "Defines Context"。
我重现了您的问题并找到了解决方案。 它不涉及更改segue方法或更改故事板中的某些属性。
建议:
但在开始解决方案之前,我想补充一点,模态呈现的视图控制器的目的是扰乱应用程序的实际流程,并呈现一些额外的上下文信息或一些可操作的内容以呈现 vc。简而言之,这是非常合乎逻辑的,实际上建议在模态呈现视图控制器时覆盖选项卡栏。应用商店里有很多很好的例子。话虽如此,这是我提出的解决方案。
解法:
我认为问题在于 UITabBarController 处理其视图层次结构的方式。 我所做的是在选项卡更改之前明确关闭模态呈现的视图控制器。这使得呈现视图控制器在选项卡栏切换到新选项卡之前一直存在于 UITabBarViewController 的视图层次结构中。在模态呈现的 "viewWillDisappear" 方法中 ViewController 添加这个。
- (void)viewWillDisappear:(BOOL)animated {
[self dismissViewControllerAnimated:true completion:^{
[super viewWillDisappear:animated];
}];
}
我在当前的 swift 项目中遇到了同样的问题。我已经解决了这个问题。
然后我终于使用 NSNotificationCenter
并在更改选项卡时关闭该视图控制器以解决此问题。
我在 AppDelegate
中引用了标签栏控制器并在那里设置了委托。
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let tabbarcontroller = storyboard.instantiateViewControllerWithIdentifier("MyTabBarController") as! UITabBarController
tabbarcontroller.delegate = self
它的代表是
//MARK: - Tabbar controller delegate
extension AppDelegate : UITabBarControllerDelegate {
func tabBarController(tabBarController: UITabBarController, didSelectViewController viewController: UIViewController) {
NSNotificationCenter.defaultCenter().postNotificationName("TabBarTabChanged", object: nil)
}
}
然后我在呈现的视图控制器中添加了观察者
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PreviewPlaceVC.BackClickAction(_:)), name: "TabBarTabChanged", object: nil)
}
// MARK: - Button Click Actions
@IBAction func BackClickAction(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
它对我来说很好用。我认为在选项卡更改事件上关闭视图控制器不是一个合适的解决方案,但是关闭而不是黑屏是可以的,这也会破坏当时的导航。
尝试在应用程序 window 中呈现视图控制器。我有一个类似的问题,已通过以下代码解决:
let myNewVC = mainStoryBoard.instantiateViewController(withIdentifier: "MyNewVCId") as! MyNewVC
let navController = UINavigationController(rootViewController: myNewVC)
navController.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
let appDelegate = UIApplication.shared.delegate as? AppDelegate
appDelegate?.window?.rootViewController?.present(navController, animated: true, completion: nil)
希望这对你也有帮助。
iOS 10+ & Swift 3+
我已经很好地解决了这个问题。正在呈现视图控制器的全屏模态呈现样式。
let storyboard = UIStoryboard(name: "Main", bundle: nil) // Replace “Main” with your storyboard name
if let viewController = storyboard?.instantiateViewController(withIdentifier: “viewController Identifier”) as? ViewController {
viewController.modalPresentationStyle = .overFullScreen
self.present(viewController, animated: false, completion: {
})
}
Over full screen 会在你的标签栏(控制器)上覆盖你的视图控制器。因此,最终用户无法切换标签栏(除非您以编程方式执行操作)标签栏项目。用户必须关闭此视图控制器才能切换标签栏。
如果您正在使用 segue,则要呈现视图控制器然后 select 'Over Full Screen' 来自属性检查中的模态呈现样式
尝试在故事板中将您的演示文稿样式设置为 'Over Full Screen' 而不是 'Over Current Context'。
我遇到了这个问题:当我展示我的 ModalController 时它采用透明背景,当我将选项卡更改为 tabBarController 中的下一个选项卡并返回到上一个选项卡时,透明背景消失了并且研究后有一个糟糕的黑色背景我发现重点是:
self.definesPresentationContext = 真
self 不是模态控制器 self 是 modalController 的呈现控制器,另一点是 .overCurrentContext 像这样
self.definesPresentationContext = true
modalController.modalPresentationStyle = .overCurrentContext
self.present(modalController, animated: true, completion: nil)
在调用 ViewController!
之前,我还需要一个 Navigation Controller并且我之前使用了描述的代码:
let newVC = self.storyboard?.instantiateViewController(withIdentifier: "newViewController")
self.definesPresentationContext = true
self.providesPresentationContextTransitionStyle = true
newVC?.modalPresentationStyle = .overCurrentContext //do NOT use .currentContext --> it will produce a black screen by switching over tabbar and close VC
self.present(newVC!, animated: false)