Повторное использование xiv в раскадровке

Мне обычно нравится создавать и создавать свои uiviews в построителе интерфейса. Иногда мне нужно создать единый вид в xib, который можно повторно использовать в нескольких диспетчерах представлений в раскадровке.

Ответ 1

Повторное использование и рендеринг xib в раскадровке.

Протестировано с помощью Swift 2.2 и Xcode 7.3.1

1 ---- Создайте новый UIView с именем "DesignableXibView"

  • Файл > Создать > Файл > Источник > Cocoa Класс касания > UIView

2 ---- Создайте соответствующий файл xib с именем "DesignableXibView"

  • Файл > Создать > Файл > Пользовательский интерфейs > Просмотр

3 ---- Установите владельца файла xib

  • выберите xib
  • выбрать владельца файла
  • установить индивидуальный класс в "DesignableXibView" в Identity Inspector.

Setting a Xib's Owner to a Custom Class

  • Примечание. Не устанавливайте пользовательский класс представления в xib. Только владелец файла!

4 ---- Внедрение DesignableXibView

//  DesignableXibView.swift

import UIKit

@IBDesignable

class DesignableXibView: UIView {

    var contentView : UIView?

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

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

    func xibSetup() {
        contentView = loadViewFromNib()

        // use bounds not frame or it'll be offset
        contentView!.frame = bounds

        // Make the view stretch with containing view
        contentView!.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]

        // Adding custom subview on top of our view (over any custom drawing > see note below)
        addSubview(contentView!)
    }

    func loadViewFromNib() -> UIView! {

        let bundle = NSBundle(forClass: self.dynamicType)
        let nib = UINib(nibName: String(self.dynamicType), bundle: bundle)
        let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView

        return view
    }

}

5 ---- Протестируйте ваш повторно используемый вид в раскадровке

  • Откройте раскадровку
  • Добавить представление
  • Установить этот вид Custom Class
  • Подождите секунду... BOOM!!

Xib Rendering Inside a Storyboard View Controller

Ответ 2

NEW! обновленный ответ с возможностью рендеринга непосредственно в раскадровке (и быстро!)

Работает в Xcode 6.3.1

Создать новый UIView с именем 'ReuseableView'

  • Файл > Создать > Файл > Источник > Cocoa Класс касания > UIView

Создайте соответствующий xib файл с именем 'ReuseableView'

  • Файл > Создать > Файл > Пользовательский интерфейs > Просмотр

Установить владельца файла xib

  • выберите xib
  • выбрать владельца файла
  • установите специальный класс в "ReusableView" в Identity Inspector. enter image description here

    • Примечание. Не устанавливайте пользовательский класс представления в xib. Только владелец файла!

Сделайте вывод из представления в ReuseableView.xib на интерфейс ReuseableView.h

  • Открыть редактор ассистентов
  • Управление + Перетаскивание из представления в интерфейс

enter image description here

Добавить реализацию initWithCoder для загрузки представления и добавления в качестве подзапроса.

- (id)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if (self) {

        // 1. load the interface
        [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
        // 2. add as subview
        [self addSubview:self.view];
        // 3. allow for autolayout
        self.view.translatesAutoresizingMaskIntoConstraints = NO;
        // 4. add constraints to span entire view
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:@{@"view":self.view}]];
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:nil views:@{@"view":self.view}]];

    }
    return self;
}

enter image description here

Проверьте свой повторно используемый вид в раскадровке

  • Откройте раскадровку
  • Добавить представление
  • Установить этот вид Custom Class

enter image description here

Запустить и наблюдать! enter image description here

Ответ 3

Swift 3 & 4 Обновление до принятого ответа

1. Создайте новый UIView с именем "DesignableXibView"

  • Файл > Создать > Файл > Источник > Cocoa Класс касания > UIView

2. Создайте соответствующий xib файл с именем "DesignableXibView"

  • Файл > Создать > Файл > Пользовательский интерфейs > Просмотр

3. Установите владельца файла xib

Выберите "DesignableXibView.xib" > "Владелец файла" > установите "Пользовательский класс" в "DesignableXibView" в Инспекторе идентификации.

  • Примечание. Не устанавливайте пользовательский класс представления в xib. Только Владелец файла

4. Реализация DesignableXibView

    import UIKit

@IBDesignable

class DesignableXibView: UIView {

    var contentView : UIView!

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

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

    func xibSetup() {
        contentView = loadViewFromNib()

        // use bounds not frame or it'll be offset
        contentView.frame = bounds

        // Make the view stretch with containing view
        contentView.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]

        // Adding custom subview on top of our view (over any custom drawing > see note below)
        addSubview(contentView)
    }

    func loadViewFromNib() -> UIView! {

        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
        let view = nib.instantiate(withOwner: self, options: nil).first as! UIView

        return view
    }
} 

5 Протестируйте свое многоразовое представление в раскадровке

  • Откройте раскадровку

  • Добавить представление

  • Задайте этот вид Custom Class

Ответ 4

Функция initWithCoder в swift 2, если у кого-то возникают проблемы с переводом:

required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        UINib(nibName: String(self.dynamicType), bundle: NSBundle.mainBundle()).instantiateWithOwner(self, options: nil)
        self.addSubview(view)
        self.view.translatesAutoresizingMaskIntoConstraints = false
        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[view]|", options: NSLayoutFormatOptions.AlignAllCenterY , metrics: nil, views: ["view": self.view]))
        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[view]|", options: NSLayoutFormatOptions.AlignAllCenterX , metrics: nil, views: ["view": self.view]))
    }

Ответ 5

Если кому-то интересно, здесь версия Xamarin.iOS кода Шаг 4 из @Garfbargle

public partial class CustomView : UIView
    {
        public ErrorView(IntPtr handle) : base(handle)
        {

        }

        [Export("awakeFromNib")]
        public override void AwakeFromNib()
        {
            var nibObjects = NSBundle.MainBundle.LoadNib("CustomView", this, null);
            var view = (UIView)Runtime.GetNSObject(nibObjects.ValueAt(0));
            view.Frame = Bounds;
            view.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;

            AddSubview(rootView);
        }
    }