UIButtonやUITableViewなど、UIKitではさまざま便利な部品が提供されています。

これら標準で提供されている部品を、その都度組み合わせて使用することもできますが、自分がよく使用する部品を組み合わせてカスタムパーツ準備しておき、さまざまな場面で使い回していくこともできます。

今回はこの再利用可能な部品である「カスタムビュー」の基本的な作成方法と使用方法を説明したいと思います。

最初は少し複雑に思えますが、Interface Builderを使って作業することもできるので、通常の画面を作成するのとほぼ同じ労力で手軽に作成することが可能です。

CustomView.xibの作成

まず部品の見た目を定義するxibファイルを作成します。Xcodeのメニューで「File > New > File」を選択し、「User Interface」の中にある「View」を選びます。名前はなんでもかまいませんが、今回はCustomView.xibとして保存します。

Customview1

Interface Builderでビューの中に部品を配置していきます。

今回はLabelを2つ設置しましたが、最初は簡単な部品から動作を確認しつつ拡張していくのがおすすめです。部品はオートレイアウトで伸縮できるように設定しておくと、使用時の柔軟性が高まり便利です。

CustomViewクラスの作成

次にソースコードを作成します。「File > New File」から「Source」の中にある「Cocoa Touch Class」を選びます。親クラスをUIViewとしてCustomViewクラスを作成します。

ソースコードは以下となります。説明の都合上アウトレットがすでに存在しますが、実際は後からInterface Builderを使って接続します。

import UIKit

@IBDesignable class CustomView: UIView {
    
    @IBOutlet weak var label1: UILabel!
    
    @IBOutlet weak var label2: UILabel!
    override init(frame: CGRect) {
        super.init(frame: frame)
        loadFromNib()
    }
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        loadFromNib()
    }
    
    private func loadFromNib() {
        let v = UINib(nibName: "CustomView", bundle: Bundle(for: CustomView.self)).instantiate(withOwner: self, options: nil)[0] as! UIView
        v.frame = self.bounds
        addSubview(v)
    }
    
    override func prepareForInterfaceBuilder() {
        loadFromNib()
    }
}

イニシャライザの中からloadFromNib()が必ず呼び出されていることに注目してください。

このコードによってCustomView.xibに定義されたView(今回は2つのラベルが設置されたカスタムビュー)が生成され、CustomViewのサブビューとして追加されることになるのです。

またオーナーとしてself(すなわちCustomViewのインスタンス)が指定されているところも要注意です。今回はxibファイルのFile’s OwnerとしてCustomViewを指定するのでオーナーはselfになるのです。この設定が矛盾しているとエラーが発生してうまく動作しないことになります。

また@IBDesignableをつけておくとInterface Builderでインタラクティブに見た目を確認できますでつけておきましょう。

CustomView.xibのFile’s Ownerの設定

もう一度CustomView.xibをいてFile’s Ownerを選択し、Identify InspectorでClassをCustomViewに変更します。間違えてViewのClassをCustomViewにしてしまうとはまってしまうので注意が必要です。

この辺いろいろな流儀がありますが、今回のCustomViewクラスのコードの記述方法ではFile’s OwnerのほうのクラスをCustomViewにしないといけないのです。

Storyboardにはりつけて実行

いよいよ作成したCustomViewを利用できます。StoryboardにViewをドロップし、そのクラスをCustomViewに変更してみましょう。

Customview2

うまくいっている場合、その段階でInterface Builderの表示が上のように変わります。ビューのサイズを変更するとCustomView側の見た目もオートレイアウトの制約に従って適切に変更されます。

CustomViewのラベルの値を変更したい場合、配置したCustomViewをアウトレットとしてビューコントローラーなどに接続します。この場合ビューコントローラー側のソースコードは以下となります。

class ViewController: UIViewController {
    @IBOutlet weak var customView: CustomView!

    override func viewDidLoad() {
        super.viewDidLoad()
        customView.label1.text = "上のラベルです"
        customView.label2.text = "下のラベルです"
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

実行すると以下のような画面となります。

Customview3

カスタムビューが表示され、2つのラベルの値が書き換わっていることがわかります。

まとめ

カスタムビューとして再利用可能な部品をまとめていくと、iOSアプリの開発を高速化していくことができます。ライブラリとしてまとめれば複数のアプリ間で同じ部品を使い回すこともできます。

この考え方はUITableViewCellの部品化の考え方にも通じるものがあります。知っておけばいろいろな場面で役に立つ知識だといえるでしょう。