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

More than 3 years have passed since last update.

いまひとつ解せないこと(=私自身の理解不足)が多くなったので、勉強しがてらの覚え書き。

ちなみに記事は、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


問題エラー その2

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

問題なのはrequiredされているメソッドか何かが足らないとのエラー。

どうやら、子クラスUIViewにて実装するべきメソッドがあるようだ。

スクリーンショット 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

エラーが消えた。


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

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

スクリーンショット 2014-08-13 13.13.41.png

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


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

  • 親クラスで宣言したイニシャライザinitは、実装(子)クラスでoverride修飾子を付ける必要がある


さらなる疑問へ

でもここで、ド素人らしい新たな疑問。

確か、UIViewControllerNSCodingプロトコルを継承していたよね?

スクリーンショット 2014-08-13 13.19.42.png

その通り継承している。

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

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

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

スクリーンショット 2014-08-13 14.11.32.png

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

スクリーンショット 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

エラーが無くなった。


ポイント

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


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

これがXcode-β5になってエラーとして表面化してきたのであろう。

今後も、initを宣言しているプロトコルを使用すると、requiredする面倒くさい記述になるのかな?

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

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

Lovely Swift!!!