xcode 如何在 Swift 中以编程方式更改 splitViewController 中的详细视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38092605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 08:59:30  来源:igfitidea点击:

How to change detail View in splitViewController programatically in Swift

iosxcodeswiftuisplitviewcontroller

提问by Raymond Moay

I'm making an app where I have a key/value in NSUserDefaults which allows the app on start up to detect if this is the first time the app is turned on on the device. If it's the first time, I want the splitVC(which is also the rootVC)'s detail View to be my pageViewController(tutorial), else I want it to go straight into the app (another view controller, lets call it todayViewController).

我正在制作一个应用程序,我在 NSUserDefaults 中有一个键/值,它允许应用程序在启动时检测这是否是该应用程序第一次在设备上打开。如果是第一次,我希望 splitVC(也是 rootVC)的详细视图成为我的 pageViewController(教程),否则我希望它直接进入应用程序(另一个视图控制器,我们称之为 todayViewController)。

I currently have a class for my SplitVC (GlobalSplitViewController.swift), but I currently have no idea how to programmatically change the detail view in ViewDidLoad.

我目前有一个 SplitVC 类(GlobalSplitViewController.swift),但我目前不知道如何以编程方式更改 ViewDidLoad 中的详细信息视图。

Also, in storyboard, my splitVC's detail segue is connected to todayViewController and it's master segue to a menuVC, which is working perfectly.

此外,在情节提要中,我的 splitVC 的细节转场连接到 todayViewController 并且它是主控转场到一个 menuVC,它工作得很好。

Thanks in advance!

提前致谢!

Code in GlobalSplitViewController.swift:

GlobalSplitViewController.swift 中的代码:

import UIKit

class GlobalSplitViewController: UISplitViewController, UISplitViewControllerDelegate {

var firstTime: Bool!

override func viewDidLoad() {
    super.viewDidLoad()

    self.delegate = self
    firstTime = loadFistTime()

    if firstTime == true {
    //load tutorials pageVC
    } else {
   //load todayVC
    }

}

func splitViewController(svc: UISplitViewController, shouldHideViewController vc: UIViewController, inOrientation orientation: UIInterfaceOrientation) -> Bool {
    return true
}

回答by Yaroslav

Starting with iOS 8 you can use:

从 iOS 8 开始,您可以使用:

splitViewController?.showDetailViewController(vc, sender: self)

or if you want to replace primary controller

或者如果你想更换主控制器

splitViewController?.show(vc, sender: self)

回答by Altimir Antonov

In AppDelegate for example you can check your UserDefaults, and with Switch or If/else you can change the splitView. Here is an example of changing the detailViewController.

例如,在 AppDelegate 中,您可以检查您的 UserDefaults,并使用 Switch 或 If/else 您可以更改 splitView。这是更改 detailViewController 的示例。

let detailViewController = self.storyboard?.instantiateViewControllerWithIdentifier("DetailNavigationViewController") as! UINavigationController
self.splitViewController?.viewControllers[1] = detailViewController

回答by Gerd Castan

calling

打电话

splitViewController.showDetailViewController(vc, sender: self)

appears to be a good solution. But when called on an iPhone when a detailViewController is shown already on top of the masterViewController, then this call presents the detailViewController without navigationViewController and without back button. So the app is stuck.

似乎是一个很好的解决方案。但是当在 iPhone 上调用 detailViewController 时已经在 masterViewController 的顶部显示了,那么这个调用会显示没有 navigationViewController 和后退按钮的 detailViewController。所以应用程序卡住了。

Popping the old detailViewController and showing the new one also shows the same problem described above.

弹出旧的 detailViewController 并显示新的也显示了上述相同的问题。

What works is popping the old one, wait until the work is finished and then showing the new one.

有效的是弹出旧的,等到工作完成,然后显示新的。

The following code assumes to be implemented in the masterViewController:

以下代码假设在 masterViewController 中实现:

if let top = navigationController?.topViewController,
   top !== self {
    if let navController = splitViewController.viewControllers[0] as? UINavigationController {
        navController.popViewController(animated: false)
        DispatchQueue.main.async {
            splitViewController.showDetailViewController(vc, sender: self)
        }
        return
    }
}
splitViewController.showDetailViewController(vc, sender: self)

Th critical part is DispatchQueue.main.async. This assures that popping the old detail is finished before showing the new detail.

关键部分是DispatchQueue.main.async。这确保在显示新细节之前完成弹出旧细节。

回答by Markus

I have another proposal:

我还有一个提议:

This code works fine on iPhone. The problem is with iPad (ONLY with iPad)

此代码在 iPhone 上运行良好。问题出在 iPad(仅限 iPad)

Navigation bar on detail view still disappears (And back button to, obviously) but ONLY on iPad.

详细视图上的导航栏仍然消失(显然还有后退按钮),但仅限于 iPad。

On iPhone works perfectly.

在 iPhone 上完美运行。

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {

var window: UIWindow?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

window = UIWindow(frame: UIScreen.main.bounds)

let firstVC = FIRST()
let secondVC = SECOND()

let firstNC = UINavigationController(rootViewController: firstVC)
let secondNC = UINavigationController(rootViewController: secondVC)

let splitViewController =  UISplitViewController()
splitViewController.viewControllers = [firstNC, secondNC]
splitViewController.preferredPrimaryColumnWidthFraction = 1/3
splitViewController.delegate = self

// IMPORTANT to show back button
let navigationController = splitViewController.viewControllers[splitViewController.viewControllers.count-1] as! UINavigationController

navigationController.topViewController!.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem

window?.rootViewController = splitViewController
window?.makeKeyAndVisible()

return true
}

// MARK: - Split view
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController:UIViewController, onto primaryViewController:UIViewController) -> Bool {

guard let secondaryAsNavController = secondaryViewController as? UINavigationController else { return false }

guard let topAsDetailController = secondaryAsNavController.topViewController as? SECOND else { return false }

if topAsDetailController.detailItem == nil {
// Return true to indicate that we have handled the collapse by doing nothing; the secondary controller will be discarded.
return true
}
return false
}

The question is:

问题是:

What fails in the case of iPad?I repeat, this code on iPhone works PERFECTLY.

iPad 失败了怎么办?我再说一遍,iPhone 上的这段代码运行良好。

(And the scenario is: NO storyboard)

(场景是:没有故事板