Использование объекта XIB внутри другого XIB - PullRequest
17 голосов
/ 23 февраля 2011

Я проектирую, используя IB конкретную кнопку (с некоторыми надписями, imageView и другими вещами).

Тогда я бы хотел использовать этот объект (кнопку) xib в другой xib, где у меня есть6 объектов этой кнопки.

Я знаю, что могу сделать это программно, используя Идентификатор класса, но затем мне нужно расположить свои метки и вид изображения, а также установить значения по умолчанию и все остальное в коде.

Мне интересно, возможно ли сделать то же самое, используя только IB?(конечно, я все равно установил бы значения в коде, но я хочу, чтобы позиции lables / imageView и все остальные были установлены в xib)

Спасибо

Редактировать

Итак, я понимаю, что то, о чем я просил сначала, невозможно.То, что я сейчас пытаюсь сделать, таково:

Я создал ButtonTest.xib.Внутри Xib у меня есть UIView и 3 подпредставления (2 ярлыка и кнопка).В инспекторе я установил класс UIView на ButtonTest.Внутри ButtonTest.m у меня есть 3 выхода для каждого из подпредставлений, которые я подключаю в IB.

Далее у меня есть ButtonTestViewController.xib.Внутри я поместил один вид и установил его класс в инспекторе равным ButtonTest.Я подключаю это представление к myTextView розетке внутри ButtonTestViewController.m класса ButtonTest

Теперь это код внутри ButtonTestViewController.m viewDidLoad:

- (void)viewDidLoad {
    [super viewDidLoad];

    NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:@"ButtonTest" owner:nil options:nil];
    ButtonTest *mainView = (ButtonTest*)[subviewArray objectAtIndex:0];

    self.myTextView = mainView;
}

То, что я надеялся, будетслучается, что представление в ButtonTestViewController.xib станет представлением, которое я разработал в ButtonTest.xib.Это просто не происходит.происходит то, что представление внутри ButtonTestViewController.xib остается прежним.

Стоит отметить, что если я добавлю:

[self.view addSubview:mainView];

Он добавляет новое представление, помимо существующего.

Есть идеи, как сделать то, что я хочу?

В конечном итоге мне бы хотелось иметь 6 представлений в ButtonTestViewController.xib, все будет выглядеть как шаблон ButtonTest.xib, а значения lables будутустановите код.

Edit2

Хорошо, ребята, я сделал все, что вы сказали, и это сработало как шарм.Единственная проблема, с которой я сталкиваюсь сейчас, - это когда ButtonTestViewController.xib немного больше, чем ButtonTest.xib.Когда это происходит, ярлык на кнопке выглядит очень размытым.Когда они оба имеют одинаковый размер, это все хорошо.

@ Нед - я использовал точный код, который вы разместили в моем методе InitWithCoder, за исключением того, что я переключил предложение кадра на это:

self.bounds = mainView.frame;

Я пытался поиграть с режимом контента в IB, пытаясь это исправить, но безрезультатно.

Когда я использую его, как вы написали, это означает:

mainView.frame = self.bounds;

Это вообще не работаети размеры обоих видов остаются неизменными.Здесь я попытался поиграть с resizeMask, но все равно не сработало.

И идея, как исправить эти 2 проблемы?Спасибо, ребята!

Редактировать 3

Мне удалось исправить одну из проблем, изменив размер ButtonTestViewController.xib до размера ButtonTest.xib.Это то, что я сделал (используя код для решения размытой проблемы, взятый из здесь )

self.bounds = CGRectMake(0, 0, mainView.frame.size.width, mainView.frame.size.height);
        CGRect overlay2Frame = self.frame;
        overlay2Frame.origin.x = round(overlay2Frame.origin.x);
        overlay2Frame.origin.y = round(overlay2Frame.origin.y);
        self.frame = overlay2Frame;

Другая проблема, которую я до сих пор не могу решить.представление в ButtonTest.xib просто не станет больше, чтобы соответствовать другому представлению.

Ответы [ 4 ]

16 голосов
/ 23 февраля 2011

Вы можете сделать это, и довольно легко.Для этого я создаю подкласс UIView (скажем, он называется «MyView.m» и «MyView.h»), а затем перо «MyView.xib».

Сначала в перощелкните «Владелец файла» и установите для класса «MyView».Это сделает так, что IBOutlets / Actions из вашего класса будут отображаться в IB.Добавьте одно представление верхнего уровня (если оно еще не было) в качестве основного представления и добавьте другие пользовательские элементы (UILabels и UIImageViews) в качестве подпредставлений основного UIView.

Затем добавьтеследующий код, чтобы он вызывался при инициализации MyView (помните, что если вы инициализируете из пера, он будет инициализирован через - (id) initWithCoder: (NSCoder *) aDecoder).

NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
UIView *mainView = [subviewArray objectAtIndex:0];

//Just in case the size is different (you may or may not want this)
mainView.frame = self.bounds;

[self addSubview:mainView];

Что этоделает - загружает иерархию представления из вашего пера в NSArray, и, поскольку у вас был только один UIView верхнего уровня, вы просто добавляете это как подпредставление вашего пользовательского UIView.

Это позволяет вам создавать UIViews (идругие подклассы UIView) в Интерфейсном Разработчике.

РЕДАКТИРОВАТЬ: Обновлено до редактирования OP.

Я всегда делал так, сначала следуя моим указаниям выше.Одно из отличий состоит в том, что в вашем перте ButtonTest вы меняете класс UIView на ButtonTest, но я изменяю класс владельца файла на ButtonTest.Затем внутри ButtonTest.m сделайте вещи loadNibNamed.Теперь, чтобы добавить этот объект в ButtonTestViewController.xib, добавьте UIView (или UIButton, независимо от того, из какого ButtonTest подкласс), и измените класс на ButtonTest.

Это немного сбивает с толку, поэтому я попытаюсь сломатьэто вверх по файлу.

ButtonTestViewController.xib: добавить UIButton (независимо от наследования ButtonTest) и изменить класс на ButtonTest

ButtonTest.m: внутри метода initWithCoder сделать всеиз материала «loadNibNamed», который у меня есть выше

ButtonTest.xib: измените класс владельца файла на ButtonTest и свяжите все IBOutlets и IBActions

6 голосов
/ 21 ноября 2014

Некоторые из вас спрашивают в комментариях, если это решение не создает бесконечный цикл, и у меня недостаточно репутации, чтобы отвечать там, поэтому вот мой ответ:

Цикл существует, если в вашем представлении rootXIB имеет "Пользовательский класс", установленный на MyView.Это вызывает ситуацию, когда представление, загруженное из XIB, снова вызывает инициализатор MyView и, следовательно, создает бесконечный цикл.Решение состоит в том, что «Пользовательский класс» должен быть UIView, и только класс Владельца файла должен быть установлен в MyView (чтобы иметь возможность назначать IBOutlets и IBActions).

2 голосов
/ 19 мая 2017

Swift 3.0

создать файл swift с классом

class ViewXIBfileClassView: UIView {
.....
}

создать Xib файл с view: ViewXIBfileClassView

создать класс представления оболочки

class ViewWrapper: UIView {

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        let view = UINib(nibName: "ViewXIBfileClassView_file", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! viewXIBfileClassView
        self.addSubview(view)
        view.bindEdgesToSuperview()
    }
}

добавить расширение к UIView

extension UIView {
    /// Adds constraints to the superview so that this view has same size and position.
    /// Note: This fails the build if the `superview` is `nil` – add it as a subview before calling this.
    func bindEdgesToSuperview() {
        guard let superview = superview else {
            preconditionFailure("`superview` was nil – call `addSubview(view: UIView)` before calling `bindEdgesToSuperview()` to fix this.")
        }
        translatesAutoresizingMaskIntoConstraints = false
        ["H:|-0-[subview]-0-|", "V:|-0-[subview]-0-|"].forEach { visualFormat in
            superview.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: visualFormat, options: .directionLeadingToTrailing, metrics: nil, views: ["subview": self]))
        }
    }
}

Используйте UIView с ViewWrapper внутри всех файлов Xib, которые вы хотите

0 голосов
/ 24 февраля 2011

Если ваш класс, например, является подклассом UIButton, вы можете открыть библиотеку в Интерфейсном Разработчике, и она будет находиться на вкладке классов при ее поиске, и вы можете перетаскивать ее.

Вы можететакже просто перетащите UIB-кнопку и установите ее класс на панели инспектора.

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

...