SwiftのUIViewControllerでデフォルトのsuper.init()を呼び出せないのはなぜですか?


84

UIViewControllerストーリーボードからを使用しておらず、オブジェクトのinitを渡すカスタム関数が必要ですNSManagedObjectIDsuper.init()Objective-Cと同じように電話をかけたいだけです。このような:

init(objectId: NSManagedObjectID) {
    super.init()
}

しかし、次のコンパイラエラーが発生します。

スーパークラスUIViewControllerの指定された初期化子を呼び出す必要があります

私は単にこれをもうすることができませんか?

回答:


119

の指定されたイニシャライザーはUIViewControllerですinitWithNibName:bundle:。代わりにそれを呼び出す必要があります。

http://www.bignerdranch.com/blog/real-iphone-crap-2-initwithnibnamebundle-is-the-designated-initializer-of-uiviewcontroller/を参照してください

ペン先がない場合nilは、nibNameを渡します(バンドルもオプションです)。次にloadView、以前と同じようself.viewviewDidLoad、またはにサブビューを追加してカスタムビューを作成できます。


4
したがって、現在、ペン先以外のUIViewControllerサブクラスでカスタムinitメソッドを作成することは不可能ですか?
SirRupertIII 2014年

1
ああ、ありがとう!ペン先の名前に「」を渡していました。
SirRupertIII 2014年

2
ああ、少し掘り下げた後、それinitWithCoder:NSCodingプロトコルから来ていることがわかりました... UIViewControllerインスタンスの初期化におけるその役割が、UIViewControllerの「指定された」初期化子であるか、そのスーパークラスのいずれであるかはまだわかりません。 。
ニコラスMiari

6
ありがとう!すばやくコピーして貼り付けるには、letプロパティを設定した後でこれを呼び出しますsuper.init(nibName: nil, bundle: nil)
Ferran Maylinch 2017年

3
Init With coderは、状態の復元を行う必要がある場合に使用されます。状態復元機能を使用してViewControllerの状態を保存すると、コーダーは状態が保存されたときに保存した値を返します。そこから、アプリケーションを閉じたときからの最後の初期状態にViewControllerを再構築できます。したがって、ユーザーにとっては、中断したところから
Esko918 2017年

44

もう1つの優れた解決策はconvenience、次のように新しい初期化子を初期化子として宣言することです。

convenience init( objectId : NSManagedObjectID ) {
    self.init()

    // ... store or user your objectId
}

サブクラスで指定された初期化子をまったく宣言しない場合、それらは自動的に継承さself.init()れ、便利な初期化子内で使用できます。

UIViewControllerの場合、デフォルトのinitメソッドは両方の引数に対してinit(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!)withnilを呼び出します(UIViewControllerをCommandキーを押しながらクリックすると、その情報が表示されます)。

TL; TR:プログラムでUIViewControllersを操作する場合は、カスタム引数を使用して新しい初期化子を追加する完全な実例を次に示します。

class MyCustomViewController: UIViewController {
    var myString: String = ""

    convenience init( myString: String ) {
        self.init()

        self.myString = myString
    }
}

これはよりエレガントなソリューションであり、一般的なケースで機能します
Ciprian 2015年

2
拡張機能でこれを実行しようとしましたが、再帰的に自分自身を呼び出しました。
Danyal Aytekin 2015年

12
この答えの「トリック」myStringはに設定されている""ため、initは必須ではありません。このソリューションは、初期値を使用したくない場合は崩壊します。その場合は、使用する必要がありますself.init(nibName: nil, bundle:nil)
Dan Rosenstark 2015年

2
@YarまたはmyStringプロパティをオプションにする
Klaas

1
@Klaasはい:私の問題は、オプションを避けてコードをコンパイルするためだけにイニシャライザーを使用していたことです。
ダンローゼンスターク2015年

16

オキュラスの答えを改善するには:

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

15

更新:リンクを追加

https://developer.apple.com/documentation/uikit/uiviewcontroller/1621359-init

iOSのドキュメントによると、UIViewControllerの指定されたイニシャライザーはinitWithNibName: bundle:です。

UIViewControllerをサブクラス化する場合は、NIBを使用していない場合でも、このメソッドのスーパー実装を呼び出す必要があります。

あなたは次のようにそれを行うことができます:

init(objectId : NSManagedObjectID) {

    super.init(nibName: (xib's name or nil'), bundle: nil)

   // other code...
}

または

新しい初期化子を便利な初期化子として宣言します。

 convenience init( objectId : NSManagedObjectID ) {

    self.init()

     // other code...

}


1
スクリーンショットとして残すのではなく、帰属のためにオリジナルにリンクする必要があります。
ネイサンタギー2017年

@NcNcが言ったのと同じプロセスを使用しました。それは私のために働いた。リンクは
Anil Gupta

@NathanTuggyいいえ、彼はすべきではありません。リンクには、いつか期限切れまたは移動する機能があります。探している情報ではなく、404エラーを見たい人はいますか?
mykolaj

1
@mykolaj:この回答では、情報はすでにここにあります。(そうでなければ、リンクのみの回答として削除のフラグを立てていたでしょう。)しかし、これを読んだ人がどこから来たのかを見つけてクレジットできるように、帰属も重要です。スクリーンショットはそのためには機能しませんが、リンクは機能します。リンク切れの場合、それは残念なことですが、まったくクレジットが与えられないよりも悪い状況だとは言えません。SOがリンクのみの回答をしなければならない異議は、リンクのみの回答です。リンクではありません。リンク情報望ましい定式化です。
ネイサンタギー

@NathanTuggyリンクを追加しました。思い出させてくれてありがとう
NcNc 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.