Пользовательский UIView пуст при создании экземпляра из XIB в Swift 4 - PullRequest
0 голосов
/ 03 декабря 2018

У меня есть пользовательское представление, которое я пытаюсь загрузить из пользовательского XIB, но при загрузке оно выглядит пустым, даже при том, что при отладке оно имеет правильные размеры.

Мои операторы отладки показывают, чтофрейм имеет правильные размеры:

commonInit ()
XIB: MyCustomView
фрейм myView: (0.0, 0.0, 320.0,568.0)
myView ContentSize: (320.0, 710.0)

Это мой пользовательский виртуальный канал, который я использую для вызова своего пользовательского представления

class MyCustomViewController: UIViewController {

    var myView : MyCustomView!

    override func viewDidLoad() {
        super.viewDidLoad()

        myView = MyCustomView(frame: self.view.frame)

        self.view.addSubview(myView)

        updateScrollViewSize()

        print("myView Frame: \(myView.frame)")
        print("myView ContentSize: \(myView.contentView.contentSize)")

    }

    func updateScrollViewSize () {
        var contentRect = CGRect.zero
        for view in myView.contentView.subviews {
            contentRect = contentRect.union(view.frame)
        }
        myView.contentView.contentSize = CGSize(width: myView.contentView.frame.size.width, height: contentRect.size.height + 5)
    }
}

Существует XIB, для которого владельцем файла является MyCustomView и все розетки правильно подключены.

class MyCustomView: UIView {

     let kCONTENT_XIB_NAME = "MyCustomView"

    @IBOutlet var contentView: UIScrollView!

    @IBOutlet weak var lbl_datein: UILabel!
    //.. A bunch of other GUI elements for the scrollview
    @IBOutlet weak var text_location: UITextField!


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

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        commonInit()
    }

    func commonInit() {
        print(#function)
        print("XIB: \(kCONTENT_XIB_NAME)")

        Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)
        contentView.addSubview(self)
        contentView.frame = self.bounds
        contentView.backgroundColor = .blue
    }
}

Кто-нибудь видит, что я сделал неправильно при попытке загрузить вид

Ответы [ 3 ]

0 голосов
/ 03 декабря 2018

Я не мог заставить это выполнить копирование / вставку кода.Может быть, не хватает какой-то настройки, но мне трудно понять, как она должна работать.Исходный код в вопросе вылетает в этой строке:

contentView.addSubview(self)

, потому что если у вас есть IBOutlets, они всегда будут nil, если вы инициализируете его с помощью MyCustomView(frame: self.view.frame).Он должен вызывать функцию initWithCoder.

Здесь много чего происходит, но вот как я бы это сделал:

class MyCustomViewController: UIViewController {

    var myView: MyCustomView!

    override func viewDidLoad() {
        super.viewDidLoad()

        myView = Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)?.first as? MyCustomView

        self.view.addSubview(myView)

        updateScrollViewSize()

        print("myView Frame: \(myView.frame)")
        print("myView ContentSize: \(myView.contentView.contentSize)")

    }

    func updateScrollViewSize () {
        var contentRect = CGRect.zero
        for view in myView.contentView.subviews {
            contentRect = contentRect.union(view.frame)
        }
        myView.contentView.contentSize = CGSize(width: myView.contentView.frame.size.width, height: contentRect.size.height + 5)
    }

}

class MyCustomView: UIView {

    let kCONTENT_XIB_NAME = "MyCustomView"

    @IBOutlet var contentView: UIScrollView!

    @IBOutlet weak var lbl_datein: UILabel!
    //.. A bunch of other GUI elements for the scrollview
    @IBOutlet weak var text_location: UITextField!

}

Я предполагаю, что верхний уровеньобъект в кончике имеет класс MyCustomView, что приведет к множеству странных вещей.loadNibNamed вызовет init?(coder aDecoder: NSCoder), так что в идеале вы бы просто вызывали его из контроллера вида, а не из объекта пользовательского представления.

Что касается "не могу добавить"Ошибка "self as subview", я не видел эту ошибку во время работы, но я ожидал бы ее от этой строки:

contentView.addSubview(self)

, поскольку это именно то, что онадобавляет self как подпредставление представления, которое уже является подпредставлением self.

0 голосов
/ 03 декабря 2018

Если мой альтернативный ответ слишком велик, позвольте мне попытаться решить вашу существующую проблему.Вместо приведенных ниже;

Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)
contentView.addSubview(self)

Попробуйте;

let nibView = Bundle.main.loadNibNamed(kCONTENT_XIB_NAME, owner: self, options: nil)
self.addSubView(nibView)
0 голосов
/ 03 декабря 2018

Я собираюсь опубликовать альтернативу тому, что вы сделали, используя расширение.

extension UIView {

    @discardableResult
    func fromNib<T : UIView>(_ nibName: String? = nil) -> T? {
        let bundle = Bundle(for: type(of: self))
        guard let view = bundle.loadNibNamed(nibName ?? String(describing: type(of: self)), owner: self, options: nil)?[0] as? T else {
            return nil
        }
        view.translatesAutoresizingMaskIntoConstraints = false

        self.addSubview(view)
        view.autoPinEdgesToSuperviewEdges()
        return view
    }
}

* Обратите внимание, что я использую PureLayout для удобного управления авторазложением, вы можете просто применить ограничения вручнуюхотя вы сами, если вы не используете PureLayout.

Используя все вышеперечисленное, все, что вам нужно сделать, это позвонить по нижеприведенному номеру из вашей инициализации;

fromNib()

* Последнее замечание.Имя пользовательского представления должно совпадать с именем пера, в противном случае вы должны передать ему имя из функции fromNib.

Теперь у вас есть что-то гораздо более многократно используемое.

...