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

#はじめに
Swift初心者の自分用の備忘録的な記事となります。
一度ネットで調べながら作成し、疑問点が出てきたためteratailで質問し、改良したものです。

#要件
・UIViewをカスタムしてダイアログのように表示したい
・デザインはxibを使いたい
![スクリーンショット 2017-01-27 16.11.12.png](https://qiita-image-store.s3.amazonaws.com/0/110630/6976d20d-8c75-28aa-02ff-a52119087619.png)

#最初に作ったもの

```swift: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 = ""
}
```

```swift: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)が２度呼ばれてしまう
・ViewControllerの上に「CustomDialogそのもの」と「xibから呼び出したCustomDialog」が乗っていることになってしまう

#####聞いてみた
[【Swift3.0】カスタムビューの作成の際のベストプラクティスについて](https://teratail.com/questions/63281)

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

#改良したもの

```swift: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()
    }

}
```

```swift: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()
    }
    
}
```

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