Swift:カスタムViewController初期化子


87

UIViewControllerSwiftのサブクラスにカスタム初期化子をどのように追加しますか?

UIViewController次のようなサブクラスを作成しました。

class MyViewController : UIViewController
{
    init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
    {
        self.leftVC = leftVC;
        self.rightVC = rightVC;
        self.gap = gap;

        super.init();

        setupScrollView();
        setupViewControllers();
    }
}

実行すると、致命的なエラーが発生します。

致命的なエラー:クラス「MyApp.MyViewController」に実装されていない初期化子「init(nibName:bundle :)」を使用

カスタム初期化子を追加するときにオーバーライドinit(coder aDecoder:NSCoder)する必要があることinitをどこかで読んだので、それをオーバーライドして何が起こるか見てみましょう:

override init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);
}

これを追加すると、Xcodeはそれを文句を言いself.leftVC is not initialized at super.init callます。ですから、それも解決策にはなり得ないと思います。ではViewController、Swiftのサブクラスにカスタム初期化子を適切に追加するにはどうすればよいのでしょうか(Objective-Cではこれは問題ではないようです)。


どのようにインスタンス化しようとしていますMyViewControllerか?
マイクポラード2014

viewDidLoad()ですべてをインスタンス化してみませんか。必要な方法で初期化できます
tudoricc 2014

@MikePollard with dualViewCtrl = DualViewCtrl(leftVC:l、rightVC:r、gap:50)... initWithNib初期化子を使用する必要があることはすでにわかっています。
BadmintonCat

3
@tudoricc多くの場合、指定されたパラメーターを使用してイニシャライザーで安全に初期化されるインスタンスプロパティが必要になるためです。それ以降、viewDidLoadでこれを行うことはできません。必要なときに、プロパティが使用可能であることが保証されないためです。
BadmintonCat

申し訳ありませんが、私はviewDidLoad()をイニシャライザーと見なしています。説明に
感謝

回答:


123

解決しました!指定された初期化子を呼び出す必要があります。この場合は、nibNameを使用したinitです。

init(leftVC:UIViewController, rightVC:UIViewController, gap:Int)
{
    self.leftVC = leftVC
    self.rightVC = rightVC
    self.gap = gap

    super.init(nibName: nil, bundle: nil)

    setupScrollView()
    setupViewControllers()
}

31
それらの醜いセミコロンを取り除く:)
MobileMon 2015年

8
セミコロンが好きです。特に、Cocoa / Cocoa-Touch APIの名前と署名が途方もなく冗長な場合は、コードのあいまいさが少なくなります。Swiftの設計者が私見を削除するという悪い決断をしました。
BadmintonCat 2015年

25
私見ですが、文字を入力してもコンパイルされたバイナリに影響しない場合は、入力しないでください:)
Sam Soffes 2015

32
@SamSoffesなので、(余分な)空白をまったく使用しませんか?そして、すべての記号を1文字に難読化しますか?
ビクタージャレンカス2015年

8
このディスカッションは、シリコンバレーのタブとスペースを思い出させます
アーロン

13

より一般的なUIViewControllerの場合、Swift2.0以降でこれを使用できます。

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

11

これを完全に解決できたかどうかはわかりませんが、クラスのインターフェイスをどのように表示するか、および実際にコーダー機能が必要かどうかに応じて、以下を使用することもできます。

convenience required init(coder aDecoder: NSCoder)
{
    //set some defaults for leftVC, rightVC, and gap
    self.init(leftVC, rightVC, gap)
}

init:leftVC:rightVC:gapは指定された初期化子であるため、指定された初期init:coder化子を呼び出す便利な初期化子にすることで、実装の要件を満たすことができます。

これはより良いかもしれません

override init(coder aDecoder: NSCoder)
{
    super.init(coder: aDecoder);
}

一部のプロパティを初期化する必要がある場合は、それらを書き直す必要があるためです。


8

スウィフト5

で初期化さUIViewControllerれるカスタム初期化子を作成する場合storyBoard.instantiateViewController(withIdentifier: "ViewControllerIdentifier")

Optionalプロパティのみのカスタム初期化子を作成できます。

class MyFooClass: UIViewController {
    var foo: Foo?

    init(with foo: Foo) {
        self.foo = foo
        super.init(nibName: nil, bundle: nil)
    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.foo = nil
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.