web-dev-qa-db-fra.com

swift - Initialiser le contrôleur de vue à partir du storyboard en remplaçant init

J'ai une instance de ViewController définie dans un storyboard. Je peux l'initialiser comme suit

var myViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("myViewControllerIdentifier") as! ViewController

Existe-t-il un moyen de remplacer la méthode init de ViewController afin que je puisse l'initialiser à l'aide

var myViewController = ViewController()

J'ai essayé de remplacer init

convenience init() {
    self = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchTableViewController") as! SearchTableViewController
}

mais le compilateur n'aime pas ça. Des idées?

19
adamF

Un initialiseur de commodité doit toujours déléguer à un initialiseur désigné pour la même classe, et un initialiseur désigné doit appeler un initialiseur de superclasse.

Étant donné que la superclasse n'a pas d'initialiseur approprié, vous seriez probablement mieux servi par une méthode d'usine de classe:

static func instantiate() -> SearchTableViewController
{
    return UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SearchTableViewController") as! SearchTableViewController
}

puis utilisez:

var myViewController = SearchTableViewController.instantiate()
29
Steven McGrath

Une méthode d'usine de classe est la voie à suivre pour l'instant. Voici un protocole que vous pouvez utiliser pour ajouter rapidement la prise en charge de makeFromStoryboard à tous les UIViewController.

protocol StoryboardInstantiable {

    static var storyboardName: String { get }
    static var storyboardBundle: NSBundle? { get }
    static var storyboardIdentifier: String? { get }
}
​
extension StoryboardInstantiable {

    static var storyboardBundle: NSBundle? { return nil }
    static var storyboardIdentifier: String? { return nil }

    static func makeFromStoryboard() -> Self {
        let storyboard = UIStoryboard(name: storyboardName, bundle: storyboardBundle)

        if let storyboardIdentifier = storyboardIdentifier {
            return storyboard.instantiateViewControllerWithIdentifier(storyboardIdentifier) as! Self
        } else {
            return storyboard.instantiateInitialViewController() as! Self
        }
    }
}

Exemple:

extension MasterViewController: StoryboardInstantiable {

    static var storyboardName: String { return "Main" }
    static var storyboardIdentifier: String? { return "Master" }
}

Dans le cas où le contrôleur de vue est le contrôleur de vue initial dans le storyboard, vous pouvez simplement ignorer storyboardIdentifier.

Dans le cas où tous les contrôleurs de vue sont dans le même storyboard, vous pouvez également remplacer storyboardName sous l'extension StoryboardInstantiable et renvoyer le nom.

15
Berk