Table of Contents
Swift で、クラスのプロパティを初期化する際にはイニシャライザ(コンストラクタ)を使用します。
UIViewController のプロパティを初期化する際、自作のイニシャライザ(init)を定義して任意の引数を設定したいという場合、少し特殊な書き方をします。
以下では、自作の init を定義した新しい UIViewController をボタンで起動するサンプルを紹介します。
サンプルのソースコード
Single View App のプロジェクトを新規作成し、生成される ViewController.swift を以下のように変更します。
import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let button = UIButton(type: .system) button.frame = CGRect(x: 100, y: 100, width: 100, height: 40) button.setTitle("Open", for: .normal) button.addTarget(self, action: #selector(self.openVC), for: .touchUpInside) self.view.addSubview(button) } @objc func openVC(_ sender: UIButton) { let newVC = NewViewController(text: "テキスト", value: 222) self.present(newVC, animated: true, completion: nil) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } } class NewViewController: UIViewController { var text: String = "" var value: Int = 0 // 任意の引数を取る自作のイニシャライザ init(text: String, value: Int) { // 受け取った引数でプロパティを初期化 self.text = text self.value = value // クラスの持つ指定イニシャライザを呼び出す super.init(nibName: nil, bundle: nil) } // 新しく init を定義した場合に必須 required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func viewDidLoad() { super.viewDidLoad() print(text) print(value) } }
これは、起動後に表示されるボタンをタップすると、任意の引数を渡した新しい UIViewController を起動し、渡した値をコンソールに表示するアプリです。
上記のコードでは、引数に文字列 “テキスト” と数値 222 を設定しているので、以下のようにコンソールが表示されます。
ソースコードの詳細
NewViewController に、任意の引数を受け取ることのできるイニシャライザを定義しています。自作のイニシャライザでは、そのクラスが元々持つ指定イニシャライザ(Designated Initializer)を中で呼び出す必要があります。
// 任意の引数を取る自作のイニシャライザ init(text: String, value: Int) { // 受け取った引数でプロパティを初期化 self.text = text self.value = value // クラスの持つ指定イニシャライザを呼び出す super.init(nibName: nil, bundle: nil) }
また、同時に init?(coder aDecoder: NSCoder) を定義することも必須です。このイニシャライザの中には特に処理を記述する必要はありません。
// 任意の引数を取る自作のイニシャライザ init(text: String, value: Int) { // 受け取った引数でプロパティを初期化 self.text = text self.value = value // クラスの持つ指定イニシャライザを呼び出す super.init(nibName: nil, bundle: nil) } // 新しく init を定義した場合に必須 required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }
以上、任意の引数を受け取れるイニシャライザの定義方法です。
自作のイニシャライザが優先的に呼び出されるようにする
インスタンス化の際に引数を空にした場合に、自作のイニシャライザを呼び出されるようにするには convenience を使ったイニシャライザを定義します。
... // 任意の引数を取る自作のイニシャライザ init(text: String, value: Int) { // 受け取った引数でプロパティを初期化 self.text = text self.value = value // クラスの持つ指定イニシャライザを呼び出す super.init(nibName: nil, bundle: nil) } // 新しく init を定義した場合に必須 required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } convenience init() { self.init(text: "initial", value: 1) } ...
これによって NewViewController() は NewViewController(text: “initial”, value: 1) と同じになります。