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 точно так же, как в исходном xib ScrollViewPagingExampleViewController. Класс его владельца файла установлен на PagingScrollView, а его выход scrollView установлен на дочерний UIScrollView.

В ScrollViewPagingExampleViewController я просто объявляю:

IBOutlet PagingScrollView   *pagingScrollView;

А в IB я перетаскиваю View, устанавливаю его класс в PagingScrollView и подключаю выход pagingScrollView к PagingScrollView.

В awakeFromNib свойство scrollView равно нулю. Я думаю, что, поскольку scrollView подключен к IB в том же nib, к этому моменту он будет доступен.

Как ни странно, в ScrollViewPagingExampleViewController.xib есть пустой выход с именем scrollView. Это может означать, что экземпляр PagingScrollView отличается от того, который определен в PagingScrollView.xib.

В результате я не могу заполнить UIScrollView фактическими дочерними представлениями. Что я здесь делаю неправильно?


person Sofi Software LLC    schedule 02.08.2011    source источник
comment
Это не связано с вашим вопросом, но я реализовал предоставленный вами проект github по-другому. Я думаю, вам может быть интересно. Он загружен по адресу (github.com/aakash272/pagingScroll)   -  person tipycalFlow    schedule 02.08.2011
comment
Ты когда-нибудь находила решение этой проблемы, Софи? У меня аналогичная проблема, когда у меня есть ViewController и связанный с ним вид, но я пытаюсь загрузить подвид, который я создал в Interface Builder, из xib в мой родительский вид с контроллером. Выходы для подпредставления всегда нулевые, даже во время ViewWillAppear в контроллере представления для родительского представления. Однако значения по умолчанию для элементов управления отображаются во время выполнения. Я просто не нашел способ их инициализировать.   -  person Jyosua    schedule 26.06.2018


Ответы (4)


Здесь есть очень хороший ответ на этот вопрос: Доступ к представлению в awakeFromNib?

Короче говоря, представление может быть загружено в awakeFromNib, но его содержимое загружается лениво, поэтому вы должны использовать viewDidLoad вместо awakeFromNib для того, чего вы пытаетесь достичь.

person ashack    schedule 03.08.2011
comment
UIView не имеет viewDidLoad, это метод в UIViewController. В приведенном выше примере кода PagingScrollView — это UIView. Возможно, вопрос сводится к тому, как встроить пользовательский элемент управления, использующий IBOutlets, внутрь пользовательского элемента управления, который также имеет IBOutlets. - person Sofi Software LLC; 04.08.2011
comment
Я никогда не видел такого поведения ни в одном проекте... пока не начал использовать раскадровки. Кажется, это противоречит цели метода awakeFromNib? Очень странно. - person Adam; 12.04.2012
comment
Эй, Адам, я столкнулся с точно такой же проблемой сейчас. Объекты, содержащие IBOutlets, которые равны нулю в awakeFromNib при использовании объекта в раскадровке, в то время как с обычными перьями он работал нормально. - person Joris Mans; 24.01.2013
comment
Этот ответ абсолютно правильный. Никогда, никогда не делайте анимацию в awakeFromNib, это так просто. Это не сработает. рассматриваемый вид все еще анимируется и т. д., поскольку он оживает. (Это не имеет никакого значения, если вы используете раскадровки и т. Д., Это нормальная часть разработки iOS с незапамятных времен.) Что касается вопроса Софи, да, представления (как таковые) не имеют метода viewDidLoad. В той ситуации, когда у вас нет контроллера представления, вы должны вручную вызвать написанный вами метод (например, youAreLoadedPleaseRunMyAnimationsNow) из того, что является боссом представления. - person Fattie; 04.12.2013
comment
@SofiSoftwareLLC Я боролся, по сути, с той же проблемой и смог решить ее с помощью этого видео: youtube.com /watch?v=FAxtWtqeMIM - person Uzumaki Naruto; 04.09.2019

Для тех, кто найдет это и ищет подходящий ответ в 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)
}
person Sethmr    schedule 29.11.2017

У меня была эта проблема, и, как и вы, другие статьи не применялись. У меня был 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
person odyth    schedule 21.06.2015

Используя Swift, вы можете использовать элемент в своем пользовательском представлении после его установки:

class PointsTableViewCell: UITableViewCell {

    @IBOutlet weak var pointsTitleLabel: UILabel! {
        didSet {
            self.pointsTitleLabel.text = "Points"
        }
    }
}
person Nadzeya    schedule 21.03.2018