SwiftのXcode6-β5で発生したエラー解決策への疑問


いまひとつ解せないこと(=私自身の理解不足)が多くなったので、勉強しがてらの覚え書き。
ちなみに記事は、2014年8月12日現在の検証結果なので今後の動作保証は一切責任は持てません。

その解せない疑問の一つとして、`Xcode6-β5`になってから発生し始めたエラー。

#問題のエラー#

##問題エラー その1##

`Overiding declaration requires an 'override' keyword`

下段のメソッド`init(frame:CGRect)`に対する`override`修飾子を付けなさいとのエラー
単純に`Xcode6-β5`以降から`override`修飾子が必要となっただけ。
これは特に難しいこともなく納得。

![スクリーンショット 2014-08-13 12.47.27.png](https://qiita-image-store.s3.amazonaws.com/0/3184/ac2f628b-8568-7abb-999a-d5fadeb2080b.png "スクリーンショット 2014-08-13 12.47.27.png")

##問題エラー その2##

`Class 'X' does not implement its superclass's required members`

問題なのは`required`されているメソッドか何かが足らないとのエラー。
どうやら、子クラス`UIView`にて実装するべきメソッドがあるようだ。

![スクリーンショット 2014-08-10 20.32.30.png](https://qiita-image-store.s3.amazonaws.com/0/3184/7361fe5d-b301-67ff-572a-7c83baf90412.png "スクリーンショット 2014-08-10 20.32.30.png")


そこで対応策として、下記の別サイトで`required init(coder aDecoder: NSCoder!)`のイニシャライザを実装するという対処方法を発見。困った時の StackOverFlow様。

 http://stackoverflow.com/questions/25126295/swift-class-does-not-implement-its-superclasss-required-members

```
required init(coder aDecoder: NSCoder!) {
  super.init(coder: aDecoder)
}
```

![スクリーンショット 2014-08-10 20.39.10.png](https://qiita-image-store.s3.amazonaws.com/0/3184/2af02af8-4ff1-7d7a-3479-2074083df5db.png "スクリーンショット 2014-08-10 20.39.10.png")

エラーが消えた。


```MyUIView.swift
import UIKit

class MyUIView:UIView
{
    required init(coder aDecoder: NSCoder!) {
        super.init(coder: aDecoder)
    }
    
    override init(frame: CGRect)
    {
        super.init(frame: frame)
    }
}

```


#本題#

そしていよいよ、ここからが本題です。

##問題エラーに対する疑問##

ここまでで、エラーに対する対処法で『めでたしめでたし』であるのだが、自分の理解不足で、なぜエラーが発生しなくなったのかが理解できていない。

そこでさらに疑問と興味を持ったので検証&頭の中を整理をしてみる事に。

###SwiftのProtocolについての簡単な整理###
 http://qiita.com/tajihiro/items/fdbf83209b8eaa0e791b

###Swiftの継承についての簡単な整理###
http://qiita.com/tajihiro/items/3400e764d9895b248bde


###修飾子 required と override について###

プロトコルの仕組みと継承の仕組みを理解することで、何となく本題の`UIView`を継承した場合のエラーとエラー回避の仕組みが分かってきた。

```MyUIView.swift
import UIKit

class MyUIView:UIView
{
    //protocol NSCodingのイニシャライザ
    required init(coder aDecoder: NSCoder!) {
        super.init(coder: aDecoder)
    }
    
    //class UIViewのイニシャライザ
    override init(frame: CGRect)
    {
        super.init(frame: frame)
    }
}
```

元から自分で実装していた`init(frame: CGRect)`イニシャライザは、`UIView`クラスの`init(frame: CGRect)`をオーバーライドしたもの。

![スクリーンショット 2014-08-13 13.09.33.png](https://qiita-image-store.s3.amazonaws.com/0/3184/29ab1c96-ff35-ed30-d1f0-2747acbdd793.png "スクリーンショット 2014-08-13 13.09.33.png")

エラー回避の為に`MyUIView`クラスへ追加した`required init(coder aDecoder: NSCoder!)`は、`NSCoding`プロトコルで宣言されているイニシャライザであるというもの。

![スクリーンショット 2014-08-13 13.13.41.png](https://qiita-image-store.s3.amazonaws.com/0/3184/6890f0a7-540d-f882-9780-575dafbbc48b.png "スクリーンショット 2014-08-13 13.13.41.png")

とりあえず、ここまでで自分が理解したことをまとめると、イニシャライザの仕様を完全には理解していないのだが下記が説明ができる。

* プロトコルで宣言したイニシャライザ`init`は、実装クラスで`required`修飾子を付ける必要がある
* 親クラスで宣言したイニシャライザ`init`は、実装(子)クラスで`override`修飾子を付ける必要がある

#さらなる疑問へ#

でもここで、ド素人らしい新たな疑問。
確か、`UIViewController`も`NSCoding`プロトコルを継承していたよね？

![スクリーンショット 2014-08-13 13.19.42.png](https://qiita-image-store.s3.amazonaws.com/0/3184/f53136b9-a497-1e99-22d2-214113ad85f9.png "スクリーンショット 2014-08-13 13.19.42.png")

その通り継承している。
ではなぜに`MyUIViewController`と`MyUIView`では、`NSCoding`プロトコルを継承しているのに同じエラーが発生していないのか？ 以前なら、親が基本的に違うからでしょ？で済ましていたが…。

同じプロトコル`NSCoding`を実装しているのに、`View`クラスではエラーが出て、`ViewController`クラスではエラーが出ないことに対する説明ができない。

まあ文法や言語仕様を理解している人は、論理的に説明できるのだろうけど、自分は行き当たりばったりで気になる。w

![スクリーンショット 2014-08-13 14.11.32.png](https://qiita-image-store.s3.amazonaws.com/0/3184/d0b4f01d-5b0b-bf1b-ae83-2ff39f1302b9.png "スクリーンショット 2014-08-13 14.11.32.png")

そこで、`ViewController`クラスのイニシャライザにも、わざと`override`してみた。

![スクリーンショット 2014-08-13 14.24.01.png](https://qiita-image-store.s3.amazonaws.com/0/3184/aa463626-e9eb-efbf-e7c4-984b5eb20365.png "スクリーンショット 2014-08-13 14.24.01.png")

エラーが出た。

`Class 'X' does not implement its superclass's required members`

そこで、`UIViewController`にも、必殺の`NSCoding`のイニシャライザを追加してみた。

```
required init(coder aDecoder: NSCoder!) {
  super.init(coder: aDecoder)
}
```

![スクリーンショット 2014-08-13 14.27.04.png](https://qiita-image-store.s3.amazonaws.com/0/3184/fdcb6977-c156-3964-683e-098dd36948c0.png "スクリーンショット 2014-08-13 14.27.04.png")

エラーが無くなった。

#ポイント#

調べてみると、今回の場合は`UIViewController`や`UIView`が継承している数あるプロトコルの中で、`NSCoding`プロトコルのみイニシャライザ`init`が存在している。

* 実装(子)クラスでイニシャライザを`override`した(イニシャライザが重複した?)場合は、プロトコルで宣言したイニシャライザの実装が必須`required`となる。


これが`Xcode-β5`になってエラーとして表面化してきたのであろう。
今後も、`init`を宣言しているプロトコルを使用すると、`required`する面倒くさい記述になるのかな？

もっと、言語仕様を正しく理解すれば、論理的に説明できたような気がするが、とりあえずの頭の中の整理と覚え書きとして、書き殴りさせてもらいました。

ちなみに、もっとわかりやすく説明できる方々がおりましたら、ご指摘やご教授お願い致します。

**Lovely Swift!!!**