Edited at

【Swift3.0】xibを使ったカスタムビューの作り方

More than 1 year has passed since last update.


はじめに

Swift初心者の自分用の備忘録的な記事となります。

一度ネットで調べながら作成し、疑問点が出てきたためteratailで質問し、改良したものです。


要件

・UIViewをカスタムしてダイアログのように表示したい

・デザインはxibを使いたい

スクリーンショット 2017-01-27 16.11.12.png


最初に作ったもの


CustomDialog.swift

required init?(coder aDecoder: NSCoder) {

commonInitialize()
super.init(coder: aDecoder)
}

override init(frame: CGRect) {
commonInitialize()
super.init(frame: frame)
}

func setUp(frame: CGRect, name: String) {

let customDialog: UIView = Bundle.main.loadNibNamed("CustomDialog", owner: self, options: nil)?.first as! UIView

self.frame = frame
customDialog.frame = frame
dialogName = name

addSubview(customDialog)
}

func commmonInitialize() {
dialogName = ""
}



ViewController.swift

var customDialog: CustomDialog = CustomDialog()

override func viewDidLoad() {
super.viewDidLoad()

customDialog.setUp(frame: self.view.frame, name: "hoge")
}

func showDialog() {
self.view.addSubview(customDialog)
}



途中まで作ってみて


疑問点

・イニシャライザ(requiredとdesignered)が2度呼ばれてしまう

・ViewControllerの上に「CustomDialogそのもの」と「xibから呼び出したCustomDialog」が乗っていることになってしまう


聞いてみた

【Swift3.0】カスタムビューの作成の際のベストプラクティスについて


とりあえずの結論

CustomDialog.swiftをxibのFile's ownerとすることでUIViewそのものではなく、CustomDialogを呼び出すクラスとして使う


改良したもの


CustomDialog.swift

import UIKit

protocol CustomDialogDelegate: class {
func shouldDismissCustomDialog -> Void
}

class CustomDialog: NSObject {

private static let className = "CustomDialog"

var name: String

weak var customDialogDelegate: CustomDialogDelegate?

@IBOutlet var dialog: UIView!

// CustomDialogのパーツ
@IBOutlet var nameLabel: UILabel!

// MARK: IBActions

@IBAction func closeButtonTapped(sender: UIButton) {
customDialogDelegate?.shouldDismissCustomDialog()
}

// MARK: Initialize

override init() {
name = ""
super.init()
Bundle.main.loadNibNamed(CustomDialog.className, owner: self, options: nil)
}

// MARK: Public Methods

func show(presentedView: UIView?, requestName: String) {
if let unwrappedPresentedView = presentedView {
customDialog.frame = unwrappedPresentedView.frame
name = requestName

unwrappedPresentedView.addSubview(customDialog)
} else {
fatalError("View is Nil!")
}
}

func hide() {
customDialog.removeFromSuperview()
}

}



ViewController.swift

import UIKit

class ViewController: UIViewController, CustomDialogDelegate {

@IBOutlet var tableView: UITableView!

var customDialog: CustomDialog = CustomDialog()

override func viewDidLoad() {
super.viewDidLoad()

customDialog.customDialogDelegate = self
}

func showCustomDialog() {
customDialog.show(presentedView: self.navigationController?.view, requestName: "hoge")
}

func shouldDismissCustomDialog() {
customDialog.hide()
}

}


改善案等ございましたらコメントいただけると嬉しいです。