LoginSignup
37
35

More than 5 years have passed since last update.

[Swift 1.2] UIViewの自作subclassの初期化

Last updated at Posted at 2015-05-25

以前に投稿した
[Swift] UIViewの自作subclassの初期化
が Swift 1.2 の変更でエラーになってしまうので、1.2の記述方法で初期化してみます。
(結論コードは一番下にあります。)

まずは、新規ファイルから「Cocoa Touch Class」を選択し、以下のように設定しましょう。

  • Class: CustomClass
  • Subclass of: UIView
  • Language: Swift

(クラス名はなんでも良いです。以下の文章で出てくるので、違う名前を付けたときは置き換えてください。)
すると、こういうクラスが作られます。普通ですね。

CustomView.swift
class CustomView: UIView {

    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect) {
        // Drawing code
    }
    */

}

ViewControllerで作ったクラスを生成してみます。

ViewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()
        // さっき作ったやつ
        var myView = CustomView()
    }

普通に生成できました。

じゃあ次にオリジナルのinitを作っていきます、コンストラクターです。

CustomView.swift
    init() {
        super.init()
    }

(コメントアウトの部分は消しました。)
エラーが出てしまいます、2箇所も。

原因は2つあります。

  • UIViewのinit()は子クラスから呼ぶことは出来ない。
  • 必須の初期化メソッドが呼ばれていない。

一つ目のエラーは、UIViewのinit()は子クラスから呼ぶことは出来ない、というエラーです。
もちろんこんな風に生成することは出来ます。
var myUIView = UIView()

これはUIViewのinit()が、convenience initializerなので子クラスからは呼ぶことが出来ないんです(たぶん)。
(convenience initializerについては別途調べて見てください。)

そして二つ目のエラーは、必須の初期化メソッド(required init)が記述されていない、というエラーです。
なにかしらのinitを記述した際には、もし親クラスに required init があった場合は、
それを必ずオーバーライドしなくてはいけません。
(requiredそれがしについては別途調べて見てください。)

それではエラーが出ないように修正していきます。
まず2つ目のエラーから修正していきます。
2つ目のエラーの対処は簡単です。

行番号の横に出るエラーのアイコンをクリックして、エンターを押せば自動で必須メソッドをオーバーライドしてくれます。

CustomView.swift
    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

このメソッドが呼ばれるのは、コードによる生成ではなく、StoryBoardやXibでCustomViewを使うと呼ばれるようになります。
fatalErrorは単純にアプリがエラーで止まります。
コードでしか生成しない場合は、そのままにしておきます。
クラスを作っていく工程で、コードでの生成しか想定しておらず、万一StoryBoardでCustomViewを使ってしまってもエラーで止まってくれるので、想定していないバグを未然に防ぐことができますね。

では、次にinit()を使えるようにしましょう。
まず結論(のコード)から先に書いてしまうと以下のようになります。

CustomView.swift
class CustomView: UIView {

    init() {
        super.init(frame: CGRectZero)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

init()の中では、super.init(frame: CGRect)を呼ぶようにしました。
(CGRectZeroはCGRectMake(0, 0, 0, 0)と同じです。)

super.init(frame: CGRect)は子クラスからも呼べるイニシャライザです。
(convenienceかdesignatedそれがしの違いです。)

これでUIViewの自作subclassの初期化が出来ました。
わかりやすさを優先に結構省略して書いたので、足りない説明もあるかと思いますが、
詳しい説明は色々な方がQiitaに投稿されているのでそちらをご覧ください。

37
35
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
35