IBOutlet равен нулю, но он подключен в раскадровке, Swift

использование Swift 1.1 и Xcode 6.2.

у меня есть UIStoryboard, содержащий сингулярный, пользовательский UIViewController подкласс. На нем у меня есть @IBOutlet подключение типа UIView от этого контроллера до UIView подкласс на раскадровке. У меня также есть аналогичные выходы для подвидов этого вида. См. рисунок А.

но во время выполнения эти свойства равны нулю (рисунок B). Хотя я заверил я подключил розетки в интерфейсе Строитель.

мысли:

  • возможно ли, что, поскольку я использую подкласс подкласса, что-то испортит инициализацию? Я не переопределяю никакие инициализаторы
  • awakeFromNib: не вызывается по какой-то причине
  • возможно, он не подключается к subviews на subviews

вещи, которые я пробовал:

  • соответствующего @IBOutlet и раскадровка типы точно (вместо UIView)
  • Удаление свойств и розетки и повторное добавление их

Figure A

Рисунок A*

Figure B

Рисунок B

*скрытый код в Figure A - это:

@IBOutlet private var annotationOptionsView: UIView!
@IBOutlet private var arrivingLeavingSwitch: UISegmentedControl!

спасибо.

28 ответов


обычно это происходит потому, что контроллер представления еще не загрузил иерархию представлений. Контроллер представления загружает иерархию представлений только тогда, когда что-то отправляет ему view сообщение. Система делает это, когда пришло время фактически поместить иерархию представления на экран, что происходит после таких вещей, как prepareForSegue:sender: и viewWillAppear: вернулись.

поскольку ваш VC еще не загрузил свою иерархию представлений, ваши выходы по-прежнему равны нулю.

вы можете заставить VC загрузить его иерархия представления, говоря _ = self.view.


вы пробовали запустить продукт > очистить. Решил для меня очень похожую проблему.


вы создали экземпляр своего контроллера вида из раскадровки или пера, или вы создали его непосредственно через инициализатор?

Если вы создали экземпляр класса непосредственно с инициализатор, розетки не подключены. Interface Builder создает настраиваемые экземпляры ваших классов и кодирует эти экземпляры в NIBs и раскадровки для повторного декодирования, он не определяет сами классы. Если это была ваша проблема, вам просто нужно изменить код, где вы создайте свой контроллер использовать методы UIStoryboard, или UINib.


раскадровка не распознала никаких дополнительных UI-вещей, которые я добавил к ней. Во время выполнения Все ссылки были нулевыми. Поэтому я очистил папку производных данных, а затем эти соединения снова работали.


в моем случае это произошло потому, что я переопределил loadView метод в моем подклассе ViewController, но забыл добавить [super loadView]

-(void)loadView {
// blank
}

при переопределении loadView метод, это ваша ответственность за инициализацию ваших подвидов. Поскольку вы переопределяете его, представления из interface builder не получают возможности конвертировать в объекты cocoa, и поэтому выходы остаются нулевыми.

если вы реализуете loadView в своем подклассе контроллера вида, то это становится вашей ответственностью загрузите элементы UI из раскадровки/xib в код.

или просто позвоните

[super loadView];

так что суперкласс получает возможность загрузить раскадровку / xib в код.


Это происходило со мной с моей пользовательской ячейкой просмотра коллекции. Оказывается, мне пришлось заменить метод registerClassforReuseIdentifier на registerNib. Это все исправило.


можно назвать controller.view чтобы принудительно загрузить представление для инициализации IBOutlets, вы сможете назначить значения.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if (segue.identifier == "identifier") {
        let controller = segue.destinationViewController as! YourController
        let _ = controller.view //force to load the view to initialize the IBOutlets

        controller.your_IBOutlet_property = xxx
        ...
        controller.delegate = self
    }
}

Это произошло для меня, потому что я случайно создавал экземпляр моего контроллера вида напрямую, а не создавал его через раскадровку. Если вы создаете экземпляр непосредственно через MyViewController() тогда розетки не будут подключены.


для меня это произошло, когда я случайно объявил класс моего контроллера вида как

class XYZViewController: UINavigationController {
}

(т. е. как UINavigationController не UIViewController).

Xcode не подхватывает эту ошибку, класс, похоже, строится нормально и переопределяет такие функции, как viewDidLoad, viewWillAppear, etc. все работает правильно. Но никто из IBOutlets подключиться.

изменения декларация

class XYZViewController: UIViewController {
}

исправлена полностью.


недавно я столкнулся с этой проблемой! Вот моя мысль. Проблема не в вас раскадровке или какой-либо проблеме с ссылкой. Речь идет о том, как вы инициируете свой ViewController. Особенно, когда вы используете Swift.(При создании файла класса в Редакторе практически ничего нет)

просто используя init() из супер класса не может инициировать ничего, что вы работали с раскадровкой. Поэтому вам нужно изменить инициализацию ViewController. Заменять let XXViewController = XXViewController() от let XXViewController = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateViewControllerWithIdentifier("XXViewController") as! XXViewController Это говорит программе перейти к раскадровке найти XXViewController и инициирует все IBOutlet в вашей раскадровки.

надеюсь, что это поможет~ GL


Для Swift 3.

func configureView() {
    let _  = self.view
}

проверьте соединение IBOutlet, если оно подключено к владельцу файла или представлению. Могут быть ошибки.


другой случай:

ваши розетки не будут установлены, пока представление контроллера вида фактически не будет создано, что в вашем случае, вероятно, происходит вскоре после initWithNibName:bundle:-в этот момент они все равно будут равны нулю. Любая настройка, которая включает эти розетки, должна происходить в методе viewDidLoad контроллера вида.


для меня, у меня же ошибка в локализованной раскадровка, элемент был добавлен в некоторые локали, а не в другом, поэтому у меня была пустая ссылка на элемент при переключении на отсутствующий элемент языка, мне пришлось удалить (избыточной) локализации раскадровку, используя https://stackoverflow.com/a/42256341/1356559.


сначала нужно загрузить иерархию представлений, чтобы создать экземпляр точек в раскадровке. Для этого можно вручную вызвать методы loadView или loadViewIfNeeded.


для меня это был сбой, потому что containerView отсутствовала.

вот мой код авария.

@IBOutlet private var containerView: UIView!  // Connected to Storyboard
override open func loadView() {
    containerView.addSubview(anotherView)
}

пропавшая вещь звала super.loadView(). Поэтому добавление его решило проблему для меня.

Код:

@IBOutlet private var containerView: UIView!
override open func loadView() {
    super.loadView()
    containerView.addSubview(anotherView)
}

еще один случай, с которым я только что столкнулся. Я изменил имя своего класса для UIViewController, но я забыл изменить имя .xib файл, где был построен интерфейс.

Как только я поймал это и сделал имена файлов отражают имя класса, все было хорошо!

надеюсь, это кому-то поможет.


есть еще один ...

Если у вас есть пользовательский класс для UITableViewCell, но вы забыли указать Custom в стиле ячейки.


вы можете проверить, загружено ли представление is.

if isViewLoaded && view.window != nil {
 //self.annotationOptionsView.
}

  1. выберите .h и .m просмотр файлов контроллера
  2. удалить ссылку на эти файлы
  3. повторно добавьте файлы в дерево проекта
  4. откройте раскадровку, в конечном итоге заново постройте проект

случайно Я подкласс моего контроллера вида с AVPlayerViewController вместо UIViewController. Воспроизводя его в UIViewController все в норме. Это должно помочь.

нет очистки сборки (normal&full), удаление папок производных данных и выход из Xcode работал для меня.


у меня была та же проблема после копирования класса (связанного с xib), чтобы повторно использовать его с другим классом viewcontroller (связанным с раскадровкой). Я забыл удалить

override var nibName

и

override var nibBundle

методы.

после их удаления мои розетки начали работать.


У меня была аналогичная проблема, когда я ранее добавил register(_:forCellReuseIdentifier:) для пользовательской ячейки после того, как я уже определил идентификатор в раскадровке. Имел этот код в функции viewDidLoad (). Как только я удалил его, он работал нормально.


Я вижу, вы используете ViewController!? в


проверьте, есть ли у вас отсутствующие или отключенные розетки.

enter image description here


Если у вас есть два main.storyboards и вы вносите изменения в неправильный, это может произойти. Это может произойти в любое время, когда вы подключаете выход из деинсталлированного storyboard.


Если вы создаете экземпляр view controller через программно. Затем попробуйте создать его, как показано ниже

let initialVC = self.storyboard?.instantiateViewController(withIdentifier: "InitialVC") as! InitialVC
напрямую
let initialVC = InitialVC()

это работает для меня.


в моем случае приложение внезапно начало сбой. Отладка показала, что все розетки были еще nil во время viewDidLoad().

мое приложение все еще использует крупка (не раскадровки) для большинства вид контроллеров. Все было на месте, все розетки подключены правильно. Я перепроверил.

мы обычно создаем экземпляры наших контроллеров представления как

let newVC = MYCustomViewController()

...который по какой-то причине работает так же долго, как и .xib называется так же, как вид класса контроллера (не уверен, как это работает, хотя. Мы не вызов init(nibName:bundle:) с нулевыми аргументами, или переопределение init() на self как это обычно...).

поэтому я попытался явно вызвать

 let newVC = MYCustomViewController(nibName: "MYCustomViewController", bundle: .main)

...только для приветствия с ошибкой исключения времени выполнения:

*** прекращение приложения из-за необработанных исключений 'NSInternalInconsistencyException', причина: 'не удалось загрузить СИБ в пачке: 'NSBundle /nicolasmiari/Library/Developer/CoreSimulator/Devices/3DA3CF21-108D-498F-9649-C4FC9E3C1A8D/data/Containers/Bundle/Application/C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app> (загружен) 'с именем 'MYCustomViewController"

и затем, я увидел это:

флажок "целевое членство".xib файл был снят.


должно быть, произошло при разрешении одного из частых слияний конфликты в отношении файла проекта Xcode.

Яблоко наверняка необходимо придумать формат файла проекта, который является более удобным для SCM.