iOSのnibで作ったViewにCustom Classを対応させて描画する
iosnibとUIViewを継承したCustomViewクラスを作成し、nibにLabelを配置して@IBOutlet
と繋げた。
import Foundation
import UIKit
import viewframework
class CustomView: UIView {
@IBOutlet weak var labelview: UILabel?
}
このCustomViewをnibのViewと対応させるのに次の2通りの方法がある。
ルートのViewのCustom Classとして設定する
nibのルートのViewのCustom ClassをCustomViewにすると、UINib.instantiate()
でCustomViewのrequired init?(coder: NSCoder)
が呼ばれインスタンスが作られるので、
それをaddSubViewすることで描画できる。
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let customView = UINib(nibName: "CustomView", bundle: Bundle(for: type(of: self))).instantiate(withOwner: nil, options: nil).first as! CustomView
customView.labelview?.text = "OK"
view.addSubview(customView)
}
}
File’s OwnerのCustom Classとして設定する
nibのFile’s OwnerのCustom ClassをCustomViewにし、
CustomView内でwithOwner: self
でnibをロードすると@IBOutlet
にインスタンスが詰まるので、ルートのViewも繋げておいてそれをaddSubViewすればCustomView以下にnibのヒエラルキーそのまま描画される。
Custom ClassがUIViewである必要は必ずしもなくロードしたviewを親のviewに直接addSubViewしても良い。
import Foundation
import UIKit
class CustomView: UIView {
@IBOutlet var view: UIView!
@IBOutlet weak var labelview: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
load()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func load() {
print("before loading nib: \(view)") // => nil
UINib(nibName: "CustomView", bundle: Bundle(for: type(of: self))).instantiate(withOwner: self, options: nil)
// = Bundle(for: type(of: self)).loadNibNamed("CustomView", owner: self, options: nil)
print("after loading nib: \(view!.superview)") // => nil
addSubview(view)
print("after adding Subview: \(view?.superview?.classForCoder)") // => Optional(sampleapp.CustomView)
}
}
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let customView = CustomView(frame: view.frame)
customView.labelview?.text = "OK"
view.addSubview(customView)
}
}
iOS13では動くがiOS12でクラッシュする問題
クラスにObjC用の別名を設定したとき元々のクラス名をCustom Classに入れるとiOS13では動くが、iOS12では
ロード時の Unknown class _TtC8xibtest210CustomView in Interface Builder file
や、
@IBOutlet
にアクセスしたときの EXC_BAD_ACCESS
でクラッシュする問題が発生した。
@objc(ExCustomView) class CustomView: UIView {
}
ObjC用の方のクラス名を指定したらいずれの環境でも動いた。補完の上でもObjCの方のクラス名が出てくる。