IBOutlet не подключен в awakeFromNib
Приведенный здесь пример кода прекрасно работает и позволяет UIScrollView отображать изображения с подкачкой и предварительным просмотром изображений до и после текущего изображения:
- http://blog.proculo.de/archives/180-Paging-enabled-UIScrollView-With-Previews.html
- https://github.com/alexrepty/Paging-Enabled-UIScrollView-With-Previews
Я пытаюсь заключить пример в единый элемент управления, который можно использовать повторно. Итак, я создал PagingScrollView:
@interface PagingScrollView : UIView {
IBOutlet UIScrollView * scrollView;
}
@property (nonatomic,retain) IBOutlet UIScrollView * scrollView;
@end
с грязью простая реализация
- (void) awakeFromNib
{
[super awakeFromNib];
NSLog(@"awake from nib");
}
В PagingScrollView.xib я поместил View, содержащий UIScrollView и ARScrollViewEnhancer, точно так же, как в исходном xib ScrollViewPagingExampleViewController. Класс владельца его файла установлен в PagingScrollView, а выход scrollView установлен в дочерний UIScrollView.
В ScrollViewPagingExampleViewController я просто заявляю:
IBOutlet PagingScrollView *pagingScrollView;
А в IB я перетаскиваю View, устанавливаю его класс в PagingScrollView и подключаю его выход pagingScrollView к PagingScrollView.
В awakeFromNib свойство scrollView имеет значение nil. Я думаю, что поскольку scrollView подключен в IB в том же самом nib, к этому моменту он будет доступен.
Смущает то, что в ScrollViewPagingExampleViewController.xib есть пустой выход с именем scrollView. Это может указывать на то, что экземпляр PagingScrollView отличается от экземпляра, определенного в PagingScrollView.xib.
В результате я не могу заполнить UIScrollView фактическими дочерними представлениями. Что я здесь не так делаю?
4 ответа
Здесь есть очень хороший ответ на этот вопрос: Доступ к View в awakeFromNib?
Короче говоря, представление может быть загружено в awakeFromNib, но его содержимое загружается лениво, поэтому вы должны использовать viewDidLoad вместо awakeFromNib для того, чего вы пытаетесь достичь.
Для тех, кто находит это ищет соответствующий ответ в 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)
}
У меня была эта проблема, и, как и вы, другие статьи не применимы. У меня был ViewController, у которого был свой вид. В.xib-файле этого ViewController я поместил представление и присвоил ему класс 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
Используя Swift, вы можете использовать элемент в вашем собственном представлении после его установки:
class PointsTableViewCell: UITableViewCell {
@IBOutlet weak var pointsTitleLabel: UILabel! {
didSet {
self.pointsTitleLabel.text = "Points"
}
}
}