Изготовление розетки для объекта из 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)

Другие вопросы по тегам