Swift: многоразовый UIView в раскадровках и ограничениях размеров

Я пытаюсь создать повторно используемый UIView в Swift, который я могу подключить к моим контроллерам представлений раскадровки. Моя ключевая проблема прямо сейчас заключается в том, что многопользовательский "виджет" UIView не полностью вписывается в поле UIView в раскадровке. Я выполнил этот учебник, чтобы настроить виджет UIView для повторного использования

  • Создал подкласс UIView и соответствующий .xib - и связал их:

    import UIKit
    
    class MyWidgetView: UIView {
    
    @IBOutlet var view: UIView!;
    
    required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder);
    
    NSBundle.mainBundle().loadNibNamed("MyWidgetView", owner: self, options: nil);
    self.addSubview(self.view);
    }
    
    }
    
  • В XIB, который является файлом интерфейса, соответствующим указанному выше коду, я использовал UIView с размером свободной формы в режиме "Моделируемые показатели" и "Масштаб для заполнения в режиме просмотра".

  • В основной раскадровке я добавил блок UIView (ту же прямоугольную форму) и изменил класс на MyWidgetView

  • Он работает, но компоненты, которые я создал в XIB, выглядят в реальном приложении, несмотря на то, что я использовал ограничения компоновки как в XIB, так и в главной раскадровке.

Смотрите скриншот. Розовая часть не должна появляться, так как это только цвет UIVIew на главной раскадровке, которую я добавил, чтобы проверить размер. Этот UIView на самом деле является MyWidgetView (после того, как я изменил класс на шаге 3. Итак, теоретически, поскольку MyWidgetView == UIView на главной раскадровке и что UIView имеет ограничения, которые делают его прямоугольным в супервизоре, тогда почему мой виджет сжимается? Синяя часть внизу должна полностью простираться. Скважинный виджет

Ответ 1

Иерархия фактического представления, загруженная из файла nib в вашем коде, добавляется через self.addSubview(self.view). Итак, кадр вашего self.view фактически не имеет отношения к его родительскому элементу, то есть MyWidgetView.

Вы можете выбрать либо добавление ограничений компоновки с помощью кода, либо просто установку его фрейма после добавления в качестве подвью. Лично я предпочитаю последнее. В моем эксперименте для меня работает следующее. Я использую Xcode 6.4, который, я думаю, не тот, который у вас есть.

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)

    if let nibsView = NSBundle.mainBundle().loadNibNamed("MyWidgetView", owner: self, options: nil) as? [UIView] {
        let nibRoot = nibsView[0]
        self.addSubview(nibRoot)
        nibRoot.frame = self.bounds
    }
}

Ответ 2

В качестве альтернативы переменный фрейм может быть переопределен. Этот код работал у меня, когда CardImgText был установлен для владельца файла для представления.

class CardImgTxt: NSView {

    @IBOutlet var view: NSView!
    override var frame: NSRect{
        didSet{
            view.frame = bounds
        }
    }

    override func drawRect(dirtyRect: NSRect) {
        super.drawRect(dirtyRect)


        // Drawing code here.
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        NSBundle.mainBundle().loadNibNamed("View", owner: self, topLevelObjects: nil)
        addSubview(view)
    }

}

если вас больше интересует эффективность, чем обновление в реальном времени. Затем замените:

    override var frame: NSRect{
        didSet{
            view.frame = bounds
        }
    }

с:

override func viewDidEndLiveResize() {
    view.frame = bounds
}