Изготовление розетки для объекта из xib-файла
У меня есть файл Hint.xib, где у меня есть несколько элементов (метка, изображение и кнопка). И у меня есть класс с именем Hint, который является подклассом UIView и который загружает этот XIB.
Вот как выглядит реализация класса Hint:
import UIKit
@IBDesignable
extension UIView {
class func fromNib<T : UIView>() -> T? {
guard
let nibs = Bundle(for: self).loadNibNamed(String(describing: self), owner: nil, options: nil),
let nib = nibs.first
else {
return nil
}
return nib as? T
}
}
class Hint:UIView {
@IBOutlet weak var hintLabel: UILabel!
private func setup(){
if let view = Hint.fromNib(){
self.addSubview(view)
view.frame = self.bounds
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
}
Текущая настройка
В настоящее время на раскадровке я добавил один контроллер представления и перетащил UIView в представление этого контроллера представления. После этого я установил его пользовательский класс Hint
, Также я использую @IBDesignable
директива и переопределить prepareForInterfaceBuilder()
чтобы все отображалось в дизайне, и все это работает, пока я не попытаюсь сделать розетку для этикетки (hintLabel
), которая является частью файла Hint.xib.
Я получаю следующую ошибку:
Завершение работы приложения из-за необработанного исключения "NSUnknownKeyException", причина: "[
setValue:forUndefinedKey:]: этот класс не соответствует значению ключа, соответствующему кодированию для ключа hintLabel."
Я выбрал свой файл Hint.xib -> Владелец файла и проверил, все ли в порядке в Identity Inspector, и кажется, что все в порядке:
Что было бы подходящим способом изменить текст этой метки либо через IB, либо через код. Кроме того, я не могу просто изменить текст этого ярлыка в Hint.xib, потому что у меня может быть несколько представлений на экране, которые загружают (из) этот xib, и все эти представления должны иметь разный текст. Я думаю, что я упускаю что-то очевидное здесь... Спасибо за ваши советы:))
2 ответа
То, что у вас есть, очень близко к работе. Проблема в том, что вам нужно установить для владельца представление подсказок, но вы пытаетесь сделать это в методе класса. self
в методе класса есть класс, тогда как вам нужно self
быть экземпляром класса. Ваш fromNib
Метод не должен быть методом класса, он может быть методом экземпляра. Вот пример:
extension UIView {
func createView<T : UIView>() -> T? {
let type = type(of:self)
guard
let nibs = Bundle(for: type).loadNibNamed(String(describing: type), owner: self, options: nil),
let nib = nibs.last
else {
return nil
}
return nib as? T
}
}
Теперь в настройках просмотра вы можете использовать if let view = createView(){ //... }
,
Проблема в том, что вы должны загрузить xib из комплекта с помощью "owner:self", поэтому он должен выглядеть следующим образом:
class Hint:UIView {
@IBOutlet var view: UIView!
@IBOutlet weak var hintLabel: UILabel!
private func setup(){
Bundle.main.loadNibNamed("Hint", owner: self, options: nil)
self.addSubview(view)
view.frame = self.bounds
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
override func prepareForInterfaceBuilder() {
super.prepareForInterfaceBuilder()
setup()
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
}
Также не забудьте установить для владельца файла класс Hint в xib-файле (не UIView)