在子 ViewController 中重用父 ViewController 故事板文件

Reuse parent ViewController storyboard file in Child ViewController

呈现 ViewController 使用故事板: 如果 newViewController 在 StoryBoard.we 中可以使用以下方法呈现它。

 let storyboard = UIStoryboard(name: "AViewController"), bundle: UIBundle.main)
let newViewcontroller = storyboard.instantiateInitialViewController() as? AViewController
  self.present(newViewcontroller, animated: false, completion: nil)

是否可以呈现一个 ViewController 不在故事板中但其父级 viewcontroller 有故事板

我已经以编程方式创建了一个 B viewcontroller(没有故事板),现在我想展示 BViewController 它应该使用 AViewController 故事板吗?

class AViewController : UIViewController
{
//this class is in storyboard which is generic design that I want to use it in different ways.
}
class BViewController : AViewController
{
....//
}
e.g.
 self.present(BViewController(), animated: false, completion: nil)?

当我呈现 BViewcontroller 时,它会为来自 super class.

的参数抛出 nil

如果您的 ViewController 确实不在 Storyboard 中,您的代码也能正常工作。您所要做的就是在没有 nibName 的情况下实例化它,如下所示:

class ViewController: UIViewController {
    init() {
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError()
    }
}

普通 Storyboard ViewControllers 依赖 coder init 来创建,但是你可以使用 nibName: nil 初始化器正常创建它们,只要你没有任何它上面的出口(这是你的情况,因为 ViewController 不在故事板上)

一切皆有可能以编程方式实现。并非所有事情都可以通过 Interface Builder 实现。故事板只是 Interface Builder 的一个组件。

从根以编程方式呈现视图控制器:

@objc private func presentViewController() {

    guard let root = UIApplication.shared.keyWindow!.rootViewController else {
        return
    }

    let destination = SomeViewController()
    destination.transitioningDelegate = YourAnimationVendor()
    destination.modalPresentationStyle = .custom
    root.present(destination, animated: true, completion: nil)

}

您可以省略过渡委托(和自定义动画供应商)并使用常用的 UIKit 动画呈现,例如 .fullScreen 而不是 .custom

@objc private func presentViewController() {

    guard let root = UIApplication.shared.keyWindow!.rootViewController else {
        return
    }

    let destination = SomeViewController()
    destination.modalPresentationStyle = .fullScreen
    root.present(destination, animated: true, completion: nil)

}

我找到了重用故事板文件或继承故事板文件的答案。

object_setClass(设置对象的 class。)将使用 BViewController Class 覆盖 AViewController 的实例。因此,在 AViewController 之上,您可以添加更多方法。

当您有相似的 viewcontroller 并稍作改动时。您必须创建不同的 viewcontroller。使用此方法,您可以使用故事板在基本 viewcontroller 上创建并重复使用 viewcontroller .

 class BViewController{
       static func vcInstanceFromStoryboard() ->BViewController? {
            let storyboard = UIStoryboard(name: "AViewController"), bundle: UIBundle.main)
            let instance = storyboard.instantiateInitialViewController() as? AViewController
            object_setClass(instance, BViewController.self) // 
            return (instance as? BViewController)!
        }
    .....
    } 

This is an example of how do we use it:
let vc = BViewController.vcInstanceFromStoryboard()
self.present(vc , animation : true)