xibのイニシャライザと、コードのイニシャライザ
引き続き、下記のアプリで行ったことをアウトプット。
xibのイニシャライザは init?(coder aDecoder: NSCoder)
で、コードのイニシャライザは init(frame: CGRect)
または独自で定義したイニシャライザになる。
上記のアプリを作成したとき、xibとコードの両方から利用できるカスタムViewが欲しくなった。
具体的に説明すると、Cellで画像を表示するViewはCellがStoryboardで定義されているのでxib経由で初期化したい。 一方、上記のアプリは画像や動画を複数同時にアップロード可能で画像Viewの数が一定ではないため、コードで初期化をコントロールしたい。
つまり、UIImageViewを継承したカスタムなイメージビューをxibとコードの両方から呼べるようにして、一つのカスタムビューで対応したいということ。
カスタムビューのイニシャライザ
MediaViewという名前のカスタムビューを作成して対応した。 xibとコードの両方から利用できるように下記のようなイニシャライザにした。 コードはSwift3です。
import UIKit final class MediaView: UIImageView { private(set) var url: URL? private let indicator: UIActivityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .gray) private let playImageView: UIImageView = UIImageView(image: UIImage(named: "play_icon")) init() { super.init(frame: .zero) isUserInteractionEnabled = true contentMode = .scaleAspectFit clipsToBounds = true translatesAutoresizingMaskIntoConstraints = false initialize() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) initialize() } private func initialize() { indicator.hidesWhenStopped = true indicator.isHidden = true indicator.translatesAutoresizingMaskIntoConstraints = false addSubview(indicator) playImageView.contentMode = .scaleAspectFit playImageView.isHidden = true playImageView.translatesAutoresizingMaskIntoConstraints = false addSubview(playImageView) NSLayoutConstraint.activate([ indicator.centerXAnchor.constraint(equalTo: centerXAnchor), indicator.centerYAnchor.constraint(equalTo: centerYAnchor), indicator.widthAnchor.constraint(equalToConstant: indicator.frame.width), indicator.heightAnchor.constraint(equalToConstant: indicator.frame.height), playImageView.centerXAnchor.constraint(equalTo: centerXAnchor), playImageView.centerYAnchor.constraint(equalTo: centerYAnchor), playImageView.widthAnchor.constraint(equalToConstant: playImageView.frame.width), playImageView.heightAnchor.constraint(equalToConstant: playImageView.frame.height) ]) } // 省略
xibとコードの両方で利用されるものをinitialize()
というメソッドにまとめた。
コードで利用する場合はframeではなく、AutoLayoutでレイアウトを定義したかったのでtranslatesAutoresizingMaskIntoConstraints = false
にした。
今回はアプリの仕様上、初期化後にレイアウトが不変だったのでinit()
で済ましたが、override init(frame: CGRect)
にしてframeを渡しても良い。
まとめ
- xibのイニシャライザは
init?(coder aDecoder: NSCoder)
で、コードのイニシャライザはinit(frame: CGRect)
または独自で定義したイニシャライザになる。 - 例えば、xibとコードの両方で利用されるものを
initialize()
というメソッドにまとめて、両方のイニシャライザから呼べば良い。