質問: swiftで書かれた以下のclassファイルのソースがあります。 ``` // レイヤーをAVPlayerLayerにする為のラッパークラス. class AVPlayerView : UIView{ required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) } override init(frame: CGRect) { super.init(frame: frame)! // ・・・(1) } override class func layerClass() -> AnyClass{ // ・・・(2) return AVPlayerLayer.self // ・・・(2) } } ``` (1) !のForced Unwrappingを付けないと > > [パス]: A non-failable initializer cannot chain to failable initializer > > 'init(coder:)' written with 'init?' > > > のエラーが発生します。これはどういった意味で、なぜ「!」が必要なのでしょう? (2) のlayerClass()をoverrideしていますが、 (2-1) 返り値が AnyClassとは? (2-2) AVPlayerLayer.selfとは? 全く見慣れないコードでどのような理解をすればいいのかわかりません。 参考になるページURLでもかまいません。ご教授のほどいただけると幸いです。
回答: > > これはどういった意味で、なぜ「!」が必要なのでしょう? > > > これは通常の`UIView`の`init()`がFailable Initializer、「失敗する可能性のある初期化子」であるためです。もし初期化に失敗した場合、`nil`を返すため、型は`AVPlayerView?`になります。 それをオーバーライドして`AVPlayerView`を返すイニシャライザを書こうとしているので、型が違うというエラーが出ます。解決する方法は、 * `!`で`AVPlayerView?`を`AVPlayerView`にUnwrapして型を一致させる * Failable Initializerをオーバーライドするときは、Failable Initializerで記述する の2つあります。 > > (前略)全く見慣れないコードでどのような理解をすればいいのかわかりません。 > > > まず、iOSのビューはすべて自動レイヤつきビュー(Layer-Backed View)であるという理解が必要です。 `UIView`の実際の描画処理は`CALayer`、つまりCore Animationが担当しています。`UIView`(およびそのサブクラス)を生成すると、それに紐付いた`CALayer`(およびそのサブクラス)が自動的に生成されているのです。 `UIView`およびそのサブクラスが、どのレイヤクラスと紐付けされているのかを伝える方法が、`layerClass()`のオーバーライドになります。 返り値の`AnyClass`は**任意の参照型**を意味しますが、これは`UIView`のAPIが動的型付け言語のObjective-Cのものなので、`id`型がそのままSwiftに直訳されているだけですね。 `AVPlayerLayer.self`のような「型名.self」の記述は公式リファレンスのMetatype Typeに記述がありますが、ある型に対してそれ自身を値として取得したい場合に使う構文です。 この記述により、`AVPlayerView`をインスタンス化する際、システムは実際の描画に使うレイヤクラスが`AVPlayerLayer`であると知ることができ、`AVPlayerLayer`もインスタンス化します。