IBOutlet не подключен в awakeFromNib
Образец кода, связанный здесь, отлично работает и позволяет UIScrollView отображать изображения с пейджингом и предварительным просмотром изображений до и после текущего изображения:
Я пытаюсь инкапсулировать пример в один элемент управления, который можно использовать повторно. Поэтому я создал PagingScrollView:
@interface PagingScrollView : UIView {
IBOutlet UIScrollView * scrollView;
}
@property (nonatomic,retain) IBOutlet UIScrollView * scrollView;
@end
с простой реализацией грязи
- (void) awakeFromNib
{
[super awakeFromNib];
NSLog(@"awake from nib");
}
В PagingScrollView.xib я помещаю представление, содержащее UIScrollView и ARScrollViewEnhancer, точно так же, как в исходном элементе ScrollViewPagingExampleViewController xib. Его класс File Owner установлен в PagingScrollView, а его sprollView - дочерний UIScrollView.
В ScrollViewPagingExampleViewController я просто объявляю:
IBOutlet PagingScrollView *pagingScrollView;
И в IB я перетаскиваю View, устанавливаю его класс в PagingScrollView и подключаю его вывод pagingScrollView к PagingScrollView.
В awakeFromNib свойство scrollView равно нулю. Я бы подумал, что, поскольку scrollView подключен к IB в одном и том же элементе, он будет доступен к этой точке.
Смутно, в ScrollViewPagingExampleViewController.xib есть пустая розетка с именем scrollView. Это может указывать на то, что существует другой экземпляр PagingScrollView, чем тот, который определен в PagingScrollView.xib.
В результате я не могу заполнить UIScrollView фактическими дочерними представлениями. Что я здесь делаю неправильно?
Ответы
Ответ 1
Здесь очень хороший ответ на этот вопрос: Доступ к View в awakeFromNib?
Короче говоря, представление может быть загружено в awakeFromNib, но его содержимое загружается лениво, поэтому вы должны использовать viewDidLoad вместо awakeFromNib для того, чего вы пытаетесь достичь.
Ответ 2
У меня была эта проблема, и, как и вы, другие статьи не применялись. У меня был ViewController, у которого был свой собственный вид. В этом файле ViewController.xib я поставил представление и дал ему класс CustomView. Это будет отлично работать, за исключением того факта, что CustomView был определен в своем собственном файле .xib, поэтому, естественно, в awakeFromNib все IBOutlets были равны нулю. Это связано с тем, что в конструкторе интерфейса нет возможности связывать файлы .xib вместе. Поэтому, когда представление ViewController появляется на экране, он пытается создать экземпляр CustomView, а не загружать файл CustomView.xib.
Здесь подробно описывается http://cocoanuts.mobi/2014/03/26/reusable/, но суть в том, что мне пришлось реализовать следующее в классе CustomView
@implementation CustomView
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
{
if (![self.subviews count])
{
NSBundle *mainBundle = [NSBundle mainBundle];
NSArray *loadedViews = [mainBundle loadNibNamed:@"CustomView" owner:nil options:nil];
return [loadedViews firstObject];
}
return self;
}
@end
Ответ 3
Для тех, кто ищет подходящий ответ в Swift 4, вы здесь.
override func awakeAfter(using aDecoder: NSCoder) -> Any? {
guard subviews.isEmpty else { return self }
return Bundle.main.loadNibNamed("MainNavbar", owner: nil, options: nil)?.first
}
Хотя, я нашел реальный секрет, что вы не подклассифицируете основной вид файла .xib. Вместо этого сделайте владельца файла классом, который вы хотите, и добавьте Nib, как внутри внутри init:
let bundle: Bundle = Bundle(for: type(of: self))
let nib: UINib = UINib(nibName: "<Nib File Name>", bundle: bundle)
if let view = nib.instantiate(withOwner: self, options: nil).first as? UIView {
view.frame = bounds
view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.translatesAutoresizingMaskIntoConstraints = true
addSubview(view)
}