Reuse parent ViewController storyboard file in Chi

2020-08-09 04:30发布

问题:

Presenting ViewController Using storyBoard: if newViewController is in StoryBoard.we can present it using the following method.

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

Is it Possible to present a ViewController which is not in storyBoard but its parent viewcontroller has storyboard

I have create a B viewcontroller programatically (No StoryBoard) ,now I would like to present BViewController and it should use the AViewController StoryBoard?

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)?

when I present BViewcontroller it throws nil for parameters which are from super class.

回答1:

Your code will work fine if your ViewController truly isn't in a Storyboard. All you have to do is instantiate it without a nibName, like this:

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

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

Normal Storyboard ViewControllers rely on the coder init to be created, but you can create them normally with the nibName: nil initializer, as long as you don't have any outlets on it (which is your case since the ViewController is not on a storyboard)



回答2:

I founded the answer to reuse the story board file or inherite the story board file.

object_setClass(Sets the class of an object.) will override instance of AViewController with BViewController Class. So on top of AViewController you can add some more methods.

when you have similar viewcontroller with small changes. you have to create different viewcontrollers. using this method you can create on basic viewcontroller with storyboard and reuse that 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)


回答3:

Everything is possible programmatically. Not everything is possible through Interface Builder. Storyboards are just a component of Interface Builder.

To present a view controller programmatically from the root:

@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)

}

You can omit the transitioning delegate (and the custom animation vendor) and present using a stock UIKit animation, like .fullScreen instead of .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)

}