web-dev-qa-db-ja.com

SwiftでUIViewControllerのinitメソッドを記述する方法

次のUIViewControllerクラスにinitメソッドを追加できません。 initメソッドでいくつかのコードを書く必要があります。 init(coder)メソッドを作成する必要がありますか?コーダーとデコーダーのメソッドを追加しても、エラーが発生します。また、パラメーターを指定せずにinitメソッドを使用しようとしましたが、これも機能しないようです。

class ViewController: UIViewController {

    var tap: UITapGestureRecognizer?

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)   {
        super.init(nibName: nil, bundle: nil)
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }

...
...
}

パラメーターなしでsuper.init()メソッドを呼び出すと、エラーは「スーパークラスの指定されたイニシャライザーを呼び出す必要があります」、パラメーターnibとバンドルを渡すとエラーは「Required initializer init(coder)」です。

Init(coder)とinit(decoder)を追加しても機能しません。

45
Ankit Goel

私が使用した:

convenience init() {
    self.init(nibName:nil, bundle:nil)
}

一部の人々は提案した:

convenience init(){
    self.init()
}

しかし、これにより無限ループが発生します。

59
Glauco Neves

これらの答えはすべて半分の答えです。一部の人々は、convenience init()を追加しているだけで(関連するinit()メソッドを提供しない場合、再帰的にそれ自体を呼び出しているため)、関連する投稿で無限ループを経験しています。スーパークラスを拡張します。この形式は、すべてのソリューションを組み合わせて問題を完全に満たします。

// This allows you to initialise your custom UIViewController without a nib or bundle.
convenience init() {
    self.init(nibName:nil, bundle:nil)
}

// This extends the superclass.
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
}

// This is also necessary when extending the superclass.
required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented") // or see Roman Sausarnes's answer
}

Edit:また、convenience init()メソッドに渡されたパラメーターを使用して、すべてのオーバーライドされたinit()なしでクラスプロパティを初期化する場合メソッドに文句を言う場合、これらのすべてのプロパティを暗黙的にラップされていないオプションとして設定できます。これはパターン Apple自体で使用 です。

30
Jamie Birch

init(nibName:bundle:)初期化子をオーバーライドする必要があります。andinit(coder:)必須の初期化子を指定し、両方でtapを初期化します

class ViewController: UIViewController {

    var tap: UITapGestureRecognizer?

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)   {
        print("init nibName style")
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }

    // note slightly new syntax for 2017
    required init?(coder aDecoder: NSCoder) {
        print("init coder style")
        super.init(coder: aDecoder)
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }
...
...
}

また、スーパークラス初期化子を呼び出すときは、nilおよびnibNamebundleだけを渡さないようにしてください。渡されたものはすべて渡す必要があります。

20
Aaron Rasmussen

代わりに便利なイニシャライザーを作成することができます。便利なイニシャライザーはinit()をオーバーライドせず、単に呼び出すだけで簡単になります。

class ViewController: UIViewController {
    var tap: UITapGestureRecognizer?
    convenience init(){
        self.init()
        tap = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
    }
}
7
Icaro

追加する必要があると思います

required init(coder aDecoder: NSCoder) {
    print("init coder")
    super.init(coder: aDecoder)
}

または

convenience init() {
    self.init()
}

あなたもinitを書く必要があります。削除しないでください

var tap: UITapGestureRecognizer?

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?)   {
    super.init(nibName: nil, bundle: nil)
}

それが役に立てば幸い

4
Ashish Kakkad

私はこの質問に出くわしました。しかし、この質問に対する基本的な答えを誰も提供していません。 Swiftの基本は次のとおりです。-スーパークラスの初期化が完了する前に、サブクラスは変数を初期化する必要があります。

したがって、Ankit Goelがクラッシュに言及したように:-「スーパークラスの指定された初期化子を呼び出す必要があります」

したがって、更新されたコードは次のようになります。

class ViewController: UIViewController {
 var tap: UITapGestureRecognizer?

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)   {
print("init nibName style")
self.tap = nil
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.tap = UITapGestureRecognizer(target: self, action: Selector(("handleTap:")))
}

required init?(coder aDecoder: NSCoder) {
print("init coder style")
self.tap = nil
super.init(coder: aDecoder)
tap = UITapGestureRecognizer(target: self, action: Selector(("handleTap:")))
 }}
2
Vinod Supnekar