ios - 无法在容器视图中切换到另一个子视图控制器
问题描述
我有一个主视图控制器、一个容器视图和 2 个子视图控制器,我希望能够在子视图控制器之间切换(例如:当应用程序第一次加载时,我希望包含 MapView 的控制器被加载,当我按下主视图中的搜索栏时,带有要加载的表的控制器)。这是我的故事板:https ://i.stack.imgur.com/rDPMe.png
MainScreen.swift
class MainScreen: UIViewController {
@IBOutlet private weak var searchBar: UISearchBar!
@IBOutlet private weak var ContainerView: UIView!
//private var openSearchBar: Bool?
private var openMapView: Bool = true
private var openPlacesList: Bool = false
private var containerView: ContainerViewController!
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//let containerView = segue.destination as? ContainerViewController
if containerView == nil{
containerView = segue.destination as? ContainerViewController
}
if openMapView == true{
containerView!.moveToMapView()
}
else if openPlacesList == true{
containerView!.MoveToOpenPlaces()
}
}
}
//search bar delegate functions
extension MainScreen: UISearchBarDelegate{
//detects when text is entered
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
openPlacesList = true
openMapView = false
containerView!.MoveToOpenPlaces()
}
}
ContainerViewController.swift:
class ContainerViewController: UIViewController {
private var childViewController: UIViewController!
private var first: UIViewController?
private var sec: UIViewController?
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MainToMap"{
first = segue.destination as! MapViewController
self.addChild(first!)
self.view.addSubview(first!.view)
self.didMove(toParent: self)
}else{
sec = segue.destination as! PlacesListController
}
if(first != nil && sec != nil){
interchange(first!,sec!)
}
}
func interchange(_ oldVc: UIViewController,_ newVc: UIViewController ){
oldVc.willMove(toParent: nil)
self.addChild(newVc)
self.view.addSubview(newVc.view)
self.transition(from: oldVc, to: newVc, duration: 2, options: UIView.AnimationOptions.transitionCrossDissolve, animations: {
newVc.view.alpha = 1
oldVc.view.alpha = 0
}, completion: { (complete) in
oldVc.view.removeFromSuperview()
oldVc.removeFromParent()
newVc.willMove(toParent: self)
})
}
func moveToMapView(){
performSegue(withIdentifier: "MainToMap", sender: nil)
}
func MoveToOpenPlaces(){
performSegue(withIdentifier: "MainToSearches", sender: nil)
}
}
问题是当我按下搜索栏时,它调用方法交换,然后它只给出一个 SIGABRT 1 错误。我尝试了本教程:https ://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/ImplementingaContainerViewController.html#//apple_ref/doc/uid/TP40007457-CH11-SW1等等,但到目前为止还没有运气。我被困在这里,不知道如何解决这个问题。
堆栈:https: //i.stack.imgur.com/Zqpm1.png SIGABR 1 错误:https ://i.stack.imgur.com/NBgEN.png
解决方案
您似乎正在尝试在子视图控制器之间手动转换,但同时使用 segues(它们为您进行自己的转换)。消除转场(除了最初的嵌入转场,如果您使用的是带有“容器视图”的情节提要),并使用他们的情节提要 ID 手动实例化子视图控制器。但是不要使用 segues 然后尝试替换prepare(for:sender:)
.
此外,当您使用 时transition(from:to:duration:options:animations:completion:)
,您不应该自己将视图添加到视图层次结构中。该方法为您执行此操作(除非您使用该showHideTransitionViews
选项,该选项告诉该方法您正在接管它,我们不需要在此处执行此操作)。同样,当您使用该transitionCrossDissolve
选项时,您也不需要弄乱 alpha。
因此,使用您引用的那篇文章中的代码片段,您可以执行以下操作:
class FirstViewController: UIViewController {
@IBOutlet weak var containerView: UIView! // the view for the storyboard's "container view"
@IBOutlet weak var redButton: UIButton! // a button to transition to the "red" child view controller
@IBOutlet weak var blueButton: UIButton! // a button to transition to the "blue" child view controller
// tapped on "transition to red child view controller" button
@IBAction func didTapRedButton(_ sender: UIButton) {
redButton.isEnabled = false
blueButton.isEnabled = true
let oldVC = children.first!
let newVC = storyboard!.instantiateViewController(withIdentifier: "RedStoryboardID")
cycle(from: oldVC, to: newVC)
}
// tapped on "transition to blue child view controller" button
@IBAction func didTapBlueButton(_ sender: UIButton) {
blueButton.isEnabled = false
redButton.isEnabled = true
let oldVC = children.first!
let newVC = storyboard!.instantiateViewController(withIdentifier: "BlueStoryboardID")
cycle(from: oldVC, to: newVC)
}
func cycle(from oldVC: UIViewController, to newVC: UIViewController) {
// Prepare the two view controllers for the change.
oldVC.willMove(toParent: nil)
addChild(newVC)
// Get the final frame of the new view controller.
newVC.view.frame = containerView.bounds
// Queue up the transition animation.
transition(from: oldVC, to: newVC, duration: 0.25, options: .transitionCrossDissolve, animations: {
// this is intentionally blank; transitionCrossDissolve will do the work for us
}, completion: { finished in
oldVC.removeFromParent()
newVC.didMove(toParent: self)
})
}
func display(_ child: UIViewController) {
addChild(child)
child.view.frame = containerView.bounds
containerView.addSubview(child.view)
child.didMove(toParent: self)
}
func hide(_ child: UIViewController) {
child.willMove(toParent: nil)
child.view.removeFromSuperview()
child.removeFromParent()
}
}
这会产生:
推荐阅读
- java - requestDispatcher.forward() 返回空白网页
- c# - "How to Prevent multiple events C#?"
- python - sqlalchemy.exc.ProgrammingError:您的 SQL 语法有错误;检查与您的 MariaDB 服务器版本相对应的手册
- angular - convert complex/nested json object to excel table
- google-cloud-platform - Google Cloud Platform 创建自定义 IAM 角色并限制对存储桶的访问
- swift - 无法从 TabBarController 访问 UIView 子类 IBOutlets
- reactjs - aws-amplify忘记密码功能,反应js发送短信而不是电子邮件
- php - 如何获取资产文件夹的绝对路径?
- c++ - Base64 编码的字符串太大,C++ 中截断尾随字符
- string - 在 Racket 中,我如何使用一个字符串句子并创建一个包含该句子中每个单词的字符串列表?