Storyboardとxibを使ってViewを小分けで管理する
はじめに
iOS(に限りませんが)でアプリ開発をしている際に,画面にでてくるコンポーネントをそれぞれ個別で設定したい場合がほとんどです. 画面内に複数のViewがある際に,それぞれのViewをxibで記載し,それをStoryboardにまとめる,という方法を使うことでViewの管理が楽になりそうなのでメモとして残しておきます.
TL;DR
- アプリ内の各画面はStoryboardで管理
- 細かいViewはxibでデザインを,UIViewクラスでoutlet経由でViewの見た目を管理する
- File's Ownerに適切にclassを設定する
- StoryboardにViewコンポーネントを配置し,Custom Classを設定
- ViewControllerにViewをOutletで紐付けすることで,Viewの管理が可能
方法
1. View1の要素をxibで作成する
「NewFile」から「View」を選ぶとxibファイルが作成できます.
このViewはラベルが2つあるので,それぞれConstraintをつけつつ配置します.
名前はTopView.xib
としました.
ちなみにSimulated MetricsのSizeをFreedomにするとこの表示上でのサイズを可変できます.
2. 上で作成したxibを持つUIViewのクラスを作成する
xibは見た目のみなので,それを持つUIViewのクラスを作り外部から扱いやすいようにします.
名前はTopView.swift
としました.
xibからViewの情報を取得し,addSubVIew
します.
この辺りの処理は以下のサイトを参考にさせていただきました.
【iOS】【swift】カスタムViewとxibを紐付ける - tanihiro.log
Swift3 [XIBファイル] コードでの呼び出し方まとめ – RE:ENGINES
xibで作ったCustomViewをStoryboardで使う
import UIKit @IBDesignable class TopView: UIView { // この2つは後のステップで追加する @IBOutlet weak var leftLabel: UILabel! @IBOutlet weak var rightLabel: UILabel! override init(frame: CGRect){ super.init(frame: frame) loadNib() } required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder)! loadNib() } func loadNib(){ let bundle = Bundle(for: type(of: self)) let nib = UINib(nibName: "TopView", bundle: bundle) let view = nib.instantiate(withOwner: self, options: nil)[0] as! UIView view.frame = self.bounds // viewのbackgroundColorはここで設定する必要がある view.backgroundColor = UIColor.cyan self.addSubview(view) } // viewの設定 func setup() { self.leftLabel.text = "left" self.rightLabel.text = "right" self.rightLabel.textColor = UIColor.red } }
3. xibのFile's ownerにCustom Classを指定
先ほど作成したxibファイルのFile's ownerにCustom ClassにTopViewクラスを指定します.
ViewのCustom classの方に設定するとEXC_BAD_ACCESS
で落ちます.
この回答を見ると書いてある(よくわかってはいないのですが,型周りの不一致らへんが原因なのかなと考えています…)
ios - Instantiate view from nib throws error - Stack Overflow
4. IBOutletで紐付け
File's ownerのCustom Classの設定が終わるとxibからTopView.swiftの方にIBOutletをつけることが可能になります. 2つのラベルのOutletを設置します.
5. アプリに表示する画面であるViewController,Storyboardを用意する
MainViewControllerという名前でViewControllerを,同様の名前でStoryboardを作成します.
Storyboardでは,Viewコンポーネントを配置し,Custom classにTopViewを指定すると,ラベル等々描画されるはず…
MainViewControllerにはOutletでViewを紐付け,TopView
のsetup()
を呼ぶようにします.
class MainViewController: UIViewController { @IBOutlet weak var topView: TopView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. topView.setup() } ...
結果の画面は↓↓↓
終わりに
エラーなどを調べているうちに全く同じ方法をしている記事を見つけました. こちらも参考に.
この記事の新規性はあまりないですが,additionalな情報をいくつか加えているのでそれでいいということで…