いまひとつ解せないこと(=私自身の理解不足)が多くなったので、勉強しがてらの覚え書き。
ちなみに記事は、2014年8月12日現在の検証結果なので今後の動作保証は一切責任は持てません。
その解せない疑問の一つとして、Xcode6-β5
になってから発生し始めたエラー。
#問題のエラー#
##問題エラー その1##
Overiding declaration requires an 'override' keyword
下段のメソッドinit(frame:CGRect)
に対するoverride
修飾子を付けなさいとのエラー
単純にXcode6-β5
以降からoverride
修飾子が必要となっただけ。
これは特に難しいこともなく納得。
##問題エラー その2##
Class 'X' does not implement its superclass's required members
問題なのはrequired
されているメソッドか何かが足らないとのエラー。
どうやら、子クラスUIView
にて実装するべきメソッドがあるようだ。
そこで対応策として、下記の別サイトでrequired init(coder aDecoder: NSCoder!)
のイニシャライザを実装するという対処方法を発見。困った時の StackOverFlow様。
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
エラーが消えた。
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
を継承した場合のエラーとエラー回避の仕組みが分かってきた。
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)
をオーバーライドしたもの。
エラー回避の為にMyUIView
クラスへ追加したrequired init(coder aDecoder: NSCoder!)
は、NSCoding
プロトコルで宣言されているイニシャライザであるというもの。
とりあえず、ここまでで自分が理解したことをまとめると、イニシャライザの仕様を完全には理解していないのだが下記が説明ができる。
- プロトコルで宣言したイニシャライザ
init
は、実装クラスでrequired
修飾子を付ける必要がある - 親クラスで宣言したイニシャライザ
init
は、実装(子)クラスでoverride
修飾子を付ける必要がある
#さらなる疑問へ#
でもここで、ド素人らしい新たな疑問。
確か、UIViewController
もNSCoding
プロトコルを継承していたよね?
その通り継承している。
ではなぜにMyUIViewController
とMyUIView
では、NSCoding
プロトコルを継承しているのに同じエラーが発生していないのか? 以前なら、親が基本的に違うからでしょ?で済ましていたが…。
同じプロトコルNSCoding
を実装しているのに、View
クラスではエラーが出て、ViewController
クラスではエラーが出ないことに対する説明ができない。
まあ文法や言語仕様を理解している人は、論理的に説明できるのだろうけど、自分は行き当たりばったりで気になる。w
そこで、ViewController
クラスのイニシャライザにも、わざとoverride
してみた。
エラーが出た。
Class 'X' does not implement its superclass's required members
そこで、UIViewController
にも、必殺のNSCoding
のイニシャライザを追加してみた。
required init(coder aDecoder: NSCoder!) {
super.init(coder: aDecoder)
}
エラーが無くなった。
#ポイント#
調べてみると、今回の場合はUIViewController
やUIView
が継承している数あるプロトコルの中で、NSCoding
プロトコルのみイニシャライザinit
が存在している。
- 実装(子)クラスでイニシャライザを
override
した(イニシャライザが重複した?)場合は、プロトコルで宣言したイニシャライザの実装が必須required
となる。
これがXcode-β5
になってエラーとして表面化してきたのであろう。
今後も、init
を宣言しているプロトコルを使用すると、required
する面倒くさい記述になるのかな?
もっと、言語仕様を正しく理解すれば、論理的に説明できたような気がするが、とりあえずの頭の中の整理と覚え書きとして、書き殴りさせてもらいました。
ちなみに、もっとわかりやすく説明できる方々がおりましたら、ご指摘やご教授お願い致します。
Lovely Swift!!!