呈现视图控制器的最佳方法

时间:2019-12-18 08:56:24

标签: ios swift

我正在研究多个框架,而我的问题只是一个“哲学的”问题。

我创建了一个实用程序功能来显示视图控制器

static func presentViewController(identifier: String, storyboardName: String = "Main", presentationStyle: UIModalPresentationStyle = .fullScreen){
    let storyboard = UIStoryboard(name: storyboardName, bundle: InternalConstants.bundle)
    var viewResult: UIViewController
    if #available(iOS 13.0, *) {
        viewResult = storyboard.instantiateViewController(identifier: identifier)
    } else {
        viewResult = storyboard.instantiateViewController(withIdentifier: identifier)
    }
    viewResult.modalPresentationStyle = presentationStyle
    var top = UIApplication.shared.keyWindow?.rootViewController
    while top?.presentedViewController != nil {
       top = top!.presentedViewController
    }
    top!.present(viewResult, animated: true, completion: nil)
}

首先,这是呈现视图控制器的正确方法还是有更好的方法?

然后,最好在导航控制器中显示视图控制器吗?

2 个答案:

答案 0 :(得分:2)

  

首先,是呈现视图控制器的正确方法还是更好的方法?

代替实用程序放入

.ONESHELL:
  

那么,是否最好在导航控制器中显示视图控制器?

导航是面向推送/弹出的,但是使用它来呈现另一个vc也没有错

答案 1 :(得分:1)

  

首先,这是呈现视图控制器的正确方法还是有更好的方法?

只要它正常工作,那是对的,这只是您做此特定事情的方式,但是就iOSUIKit而言,这样做是否正确,答案通常是通过查看rootViewController's presentedViewController来呈现viewController是一件坏事,因为它不能保证您找到的最后一个presentedViewController是一件好事,而且您不会知道直到崩溃为止,presentedViewController可能是UISearchController,并且如果您从情节提要中使用UIContentContainerContainerView,则可能会有一个小的{{1} },这可能不利于viewController的出现和消失

您将面临的另一个问题是,当您需要通过使用这种方法向呈现的viewController传入和传出数据时,甚至都没有对呈现的viewController的引用,因为您只传递了{ {1}}

UISlider的角度出发,您永远不要尝试通过直接从视图中调用函数来从identifier呈现viewController 那是不好的习惯

如果您尝试使用MVC SDK来展示任何系统UIView,就会发现您有责任实例化并展示vc,例如UIKitUIViewControllerUIImagePickerControllerUIActivityViewControllerUIDocumentPickerViewControllerUIDocumentMenuViewController

Apple本身并没有提供提供其系统vcs功能的功能

相反,如果您正在开发框架并且不想让用户访问您的viewControllers,则应使您拥有自己的窗口并为其赋予一个UIPrinterPickerController

Apple也为此提供了许多示例,出于安全原因,在UIVideoEditorController框架中,您不应引用safari Web浏览器,而是使用名为rootViewController的东西来控制演示和展示的流程。通过调用AuthenticationServicesASWebAuthenticationSession函数关闭Safari Web ViewController

您框架的用户也不总是希望使用默认的演示动画来展示viewController,他们可能希望使用自定义viewContollers动画,他们需要访问viewController上的start()属性

想象如果您采用这种方法,将无法访问cancel()上的每个公共有用属性

  

然后,最好在导航控制器中显示视图控制器吗?

至于这部分,最好在NavigationController上显示任何内容

故事板头痛 关于情节提要板初始化的麻烦,有很多文章讨论如何优化情节提要板初始化调用网站,我建议您这样做

transitioningDelegate

通过这种方式,您可以使用UIViewController初始化情节提要,以改善呼叫站点,就像这样

extension UIStoryboard {
    enum AppStoryBoards: String {
        case
        login,
        main,
        chat,
        cart
    }

    convenience init(_ storyboard: AppStoryBoards, bundle: Bundle? = nil) {
        self.init(name: storyboard.rawValue.prefix(1).capitalized + storyboard.rawValue.dropFirst(), bundle: bundle)
    }
}

然后您可以使用另一个扩展程序来初始化视图控制器

enum

然后您可以这样称呼它

let login = UIStoryboard.init(.login)

或此

extension UIStoryboard {
    func instantiateInitialVC<T: UIViewController>() -> T {
        return self.instantiateInitialViewController() as! T
    }

    func instantiateVC<T: UIViewController>(_: T.Type) -> T {
        return self.instantiateViewController(withIdentifier: String(describing: T.self)) as! T
    }
}

这样做可以改善用于显示任何viewController的整体代码

let loginVC = UIStoryboard.init(.login).instantiateInitialVC()