Подтвердить что ты не робот

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 фактическими дочерними представлениями. Что я здесь делаю неправильно?

4b9b3361

Ответ 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)
    }