Пользовательский вид, созданный с помощью Interface Builder, не отображается при вызове в других представлениях
У меня есть xib для главного окна, и я создал пользовательский вид в следующих шагах:
- Создайте новый класс, который наследует от
NSView
.
MyView.h
:
#import <Cocoa/Cocoa.h>
IB_DESIGNABLE
@interface MyView : NSTableCellView
@end
MyView.m
:
#import "MyView.h"
@implementation MyView
- (void)awakeFromNib {
NSLog(@"Post view awaking from nib.");
}
@end
- Создайте новый xib и задайте класс корневого представления классу, созданному выше. И дизайн в этом xib.
- Установить выходы из xib в класс.
И я попытался использовать это настраиваемое представление в главном окне в следующих шагах:
- Перетащите пользовательский вид в главное окно xib.
- Задайте класс этого пользовательского представления для класса, созданного выше.
Но ничего не делает. Из журнала я вижу, что код из awakeFromNib
из класса пользовательского представления выполнен. Когда я устанавливаю класс IB_DESIGNABLE
, представление становится пустым в главном окне xib, отличном от того, что я разработал.
Я попытался установить владелец файла настраиваемого представления xib в пользовательский класс, но ничего не изменилось.
Я предполагаю, что проблема заключается в том, что пользовательский вид xib файла фактически не загружен. Когда я искал его, похоже, немного ссылок на эту точную тему. Итак, как я должен достичь этой цели? I.e., спроектировать представление в IB, реализовать его методы в классе, связать эти два и выставить его точно так же, как системное представление для использования в других xibs?
ОБНОВЛЕНИЕ:
Я нашел учебник и понял, чего мне не хватает (для правильного отображения представления при его создании). Мне нужно добавить выход из представления в xib в класс вида:
@property (nonatomic, strong) IBOutlet NSView *view;
а затем загрузите его в метод (id)initWithCoder:(NSCoder *)coder
.
[[NSBundle mainBundle] loadNibNamed:@"MyView" owner:self topLevelObjects:nil];
[self addSubview:self.view];
Но представление не будет отображаться в построителе интерфейса.
Ответы
Ответ 1
Ваша догадка правильная: xib не загружается. Погрузчик nib не знает о вашем пользовательском представлении nib. Рамка nib не предоставляет возможности для определения этого соединения, поэтому вам нужно написать код для загрузки xib.
Вот что я буду делать. Добавьте свойство contentView
к своему пользовательскому представлению:
@interface MyView ()
@property (nonatomic, strong, readwrite) IBOutlet NSView *contentView;
@end
В своем пользовательском представлении nib установите собственный класс корневого представления обратно в NSView
и отключите от него все (более длинные) выходные соединения. Задайте пользовательский класс File Owner для вашего пользовательского имени класса (например, MyView
). Подключите корневой режим к файловому владельцу contentView
и подключите все остальные выходы от File Owner к соответствующим объектам в nib.
Затем реализуйте awakeFromNib
в своем подклассе пользовательского вида, чтобы загрузить nib и добавить представление контента в виде подвью:
@implementation MyView {
BOOL hasLoadedOwnNib: 1;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self loadOwnNibIfNeeded];
}
- (void)loadOwnNibIfNeeded {
if (hasLoadedOwnNib) {
return;
}
hasLoadedOwnNib = YES;
[[NSBundle bundleForClass:self.class] loadNibNamed:NSStringFromClass(self.class) owner:self topLevelObjects:nil];
self.contentView.frame = self.bounds;
self.contentView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
[self addSubview:self.contentView];
}
@end
Обратите внимание, что вы должны быть осторожны, чтобы не допускать бесконечной рекурсии. Когда ваше приложение загружает главное окно, оно создаст экземпляр MyView
и (в конечном итоге) отправит его awakeFromNib
. Затем в awakeFromNib
, MyView
загружает свой собственный nib, где он является файловым владельцем. Погрузчик nib отправляет awakeFromNib
в File Owner, и это произойдет, когда вы уже находитесь в -[MyView awakeFromNib]
. Если вы не проверите это, вы получите переполнение стека из-за неограниченной рекурсии.
Ответ 2
Вы не предоставляете никакого кода, но вот несколько проверок здравомыслия:
-
Правильно ли задаете имя nib? В iOS его кепки чувствительны, но я не думаю, что это для вас.
-
Проверьте пакет, на самом деле есть ли там? Убедитесь, что это часть цели, которую вы строите.
-
Также может быть проблема с фреймом. Убедитесь, что параметры автоматического изменения размера настроены правильно и все в кадре.
-
Еще одна проверка, которую вы можете сделать, - установить IBOutlets в фактический кадр UIView (или другого), который вас интересует. Затем в awakeFromNib вы можете убедиться, что их фрейм существует или что они существуют вообще.