从 Split ViewController 中的 Master ViewController 转到另一个 View Controller
Segue from the MasterViewController in a SplitViewController to another View Controller
我有一个 SplitViewController
,其中 UITableViewController
作为 masterViewController,UIViewController
作为 detailViewController。
当用户点击一个单元格时,我需要推送到一个新的 UITableViewController
。所以我从单元格添加了一个 segue 到 UITableViewController
。但是发生的是 UITableViewController
被添加到 masterViewController 的堆栈中。
如何从 masterViewController 推送到一个全新的 UITableViewController
?
这里是一个简单的例子,我是如何处理这些功能的(我创建了一个新的 Master-Detail Application):
故事板:
请注意,根 VC 现在是 UINavigationController
。因此 AppDelegate
必须相应地更改:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let navCtr = self.window!.rootViewController as UINavigationController
let splitViewController = navCtr.visibleViewController as UISplitViewController
let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as UINavigationController
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
splitViewController.delegate = self
return true
}
最后在 MasterViewController
中添加:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if indexPath.row % 2 == 0 {
self.performSegueWithIdentifier("showDetail", sender: nil)
} else {
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
if let let rootCtr = appDelegate.window?.rootViewController {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let newSplit = storyboard.instantiateViewControllerWithIdentifier("SplitVC") as UISplitViewController
/// Because of Apple's "Split View Controllers cannot be pushed to a Navigation Controller"
let yetAnotherNavCtr = UINavigationController(rootViewController: newSplit)
rootCtr.presentViewController(newSplit, animated: true, completion: nil)
}
}
}
重要提示:
如果您从模板创建新的 MasterDetail 应用程序,您必须断开 showDetail
segue,因为它直接链接到单元格的 selected
回调。如果您还想保留该功能,只需再次连接它,而不是从单元格本身,而是从整个 VC。为了能够像在我时髦的 didSelect...
方法中一样使用它,该方法在偶数行上执行 showDetail
segue。
Split View 演示文稿只能工作一次 - 我还没有实现整个 rootViewController 替换 - lldb 会抱怨说:Attempt to present UISplitViewController on UINavigationController whose view is not in the window hierarchy!
如果你第二次尝试这样做。但这实际上取决于您对应用程序行为方式的要求。
在 Storyboard
"SplitVC"(故事板 ID)中命名 SplitView 控制器,如果你想像我在我的代码中那样呈现 Split View 控制器。
我明白了!首先,我应该提到 Michal 的回答帮助我有了一个想法并指出了正确的方向,所以感谢他。
我做的其实很简单。在我有一个带有容器视图的视图控制器之前,容器视图嵌入了拆分视图控制器。我只是继续将那个视图控制器嵌入到导航控制器中。
然后我在情节提要中添加了我想继续使用的视图控制器,但没有附加到它。我在 masterViewController 的 didSelectRowAtIndexPath 方法中以编程方式进行。
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
if let rootVC = appDelegate.window?.rootViewController {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let mapVC = storyboard.instantiateViewControllerWithIdentifier("MapVC") as! UIViewController
rootVC.showViewController(mapVC, sender: nil)
}
我通过 AppDelegate 获得了对导航控制器 rootViewController 的引用,并将我想要的新视图控制器推送到它的堆栈。
就是这样!如果有人感兴趣,这里有一个演示 project。
我有一个 SplitViewController
,其中 UITableViewController
作为 masterViewController,UIViewController
作为 detailViewController。
当用户点击一个单元格时,我需要推送到一个新的 UITableViewController
。所以我从单元格添加了一个 segue 到 UITableViewController
。但是发生的是 UITableViewController
被添加到 masterViewController 的堆栈中。
如何从 masterViewController 推送到一个全新的 UITableViewController
?
这里是一个简单的例子,我是如何处理这些功能的(我创建了一个新的 Master-Detail Application):
故事板:
请注意,根 VC 现在是 UINavigationController
。因此 AppDelegate
必须相应地更改:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
let navCtr = self.window!.rootViewController as UINavigationController
let splitViewController = navCtr.visibleViewController as UISplitViewController
let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as UINavigationController
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
splitViewController.delegate = self
return true
}
最后在 MasterViewController
中添加:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if indexPath.row % 2 == 0 {
self.performSegueWithIdentifier("showDetail", sender: nil)
} else {
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
if let let rootCtr = appDelegate.window?.rootViewController {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let newSplit = storyboard.instantiateViewControllerWithIdentifier("SplitVC") as UISplitViewController
/// Because of Apple's "Split View Controllers cannot be pushed to a Navigation Controller"
let yetAnotherNavCtr = UINavigationController(rootViewController: newSplit)
rootCtr.presentViewController(newSplit, animated: true, completion: nil)
}
}
}
重要提示:
如果您从模板创建新的 MasterDetail 应用程序,您必须断开
showDetail
segue,因为它直接链接到单元格的selected
回调。如果您还想保留该功能,只需再次连接它,而不是从单元格本身,而是从整个 VC。为了能够像在我时髦的didSelect...
方法中一样使用它,该方法在偶数行上执行showDetail
segue。Split View 演示文稿只能工作一次 - 我还没有实现整个 rootViewController 替换 - lldb 会抱怨说:
Attempt to present UISplitViewController on UINavigationController whose view is not in the window hierarchy!
如果你第二次尝试这样做。但这实际上取决于您对应用程序行为方式的要求。在
Storyboard
"SplitVC"(故事板 ID)中命名 SplitView 控制器,如果你想像我在我的代码中那样呈现 Split View 控制器。
我明白了!首先,我应该提到 Michal 的回答帮助我有了一个想法并指出了正确的方向,所以感谢他。
我做的其实很简单。在我有一个带有容器视图的视图控制器之前,容器视图嵌入了拆分视图控制器。我只是继续将那个视图控制器嵌入到导航控制器中。
然后我在情节提要中添加了我想继续使用的视图控制器,但没有附加到它。我在 masterViewController 的 didSelectRowAtIndexPath 方法中以编程方式进行。
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
if let rootVC = appDelegate.window?.rootViewController {
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let mapVC = storyboard.instantiateViewControllerWithIdentifier("MapVC") as! UIViewController
rootVC.showViewController(mapVC, sender: nil)
}
我通过 AppDelegate 获得了对导航控制器 rootViewController 的引用,并将我想要的新视图控制器推送到它的堆栈。
就是这样!如果有人感兴趣,这里有一个演示 project。