IBOutlet - ноль, но он связан в раскадровке, Swift

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

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

Но во время выполнения эти свойства равны нулю (рисунок B). Несмотря на то, что я уверен, что подключил выходы в Interface Builder.

Мысли

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

Что я пробовал:

  • Соответствие @IBOutlet и типов элементов раскадровки точно (вместо UIView)
  • Удаление свойств и выходных файлов и их повторное добавление.

Figure A

Рисунок A *

Figure B

Рисунок B

* Неясным кодом в Figure A является:

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

Спасибо.

Ответ 1

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

Ответ 2

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

Так как ваш VC еще не загрузил свою иерархию представления, ваши выходы все еще равны нулю.

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

Ответ 3

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

-(void)loadView {
// blank
}

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

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

Или просто вызовите

[super loadView];

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

Ответ 7

Вы можете вызвать 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
    }
}

Ответ 8

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

Ответ 9

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

class XYZViewController: UINavigationController {
}

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

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

Изменение объявления на

class XYZViewController: UIViewController {
}

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

Ответ 10

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

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

Надеемся на эту помощь ~ GL

Ответ 11

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

let initialVC = self.storyboard?.instantiateViewController(withIdentifier: "InitialVC") as! InitialVC

вместо напрямую

let initialVC = InitialVC()

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

Ответ 12

Для Swift 3.

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

Ответ 13

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

Ответ 14

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

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

Обычно мы создаем наши контроллеры вида как

let newVC = MYCustomViewController()

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

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

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

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

*** Завершение работы приложения из-за невыполненного исключения "NSInternalInconsistencyException", причина: "Не удалось загрузить NIB в комплекте:" NSBundle & lt;/Users/nicolasmiari/Library/Разработчик /CoreSimulator/Devices/3DA3CF21-108D-498F-9649-C4FC9E3C1A8D данные/Контейнеры/Пачка/Применение /C543DDC1-AE86-4D29-988C-9CCE89E23543/MyApp.app & GT; (загружен) 'с именем' MYCustomViewController ''

И тогда я увидел это:

Флажок "Целевое членство" в файле .xib не был установлен.


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

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

Ответ 15

100% рабочее решение для создания ViewControllers из XIB без StoryBoards

  1. Создать класс CustomViewController: UIViewController
  2. Создать представление CustomViewControllerView.xib
  3. В CustomViewControllerView.xib в Интерфейсном Разработчике выберите Заполнители → Владелец файла
  4. В "Инспекторе атрибутов" установите Class в CustomViewController
  5. В "Инспекторе соединений" подключите "представление" к представлению верхнего уровня XIB (убедитесь, что представление верхнего уровня Класс не указывает на CustomViewController)
  6. В "Инспекторе соединений" подключите другие розетки (при необходимости/существуют)
  7. Создайте экземпляр CustomViewController в родительском контроллере представления/делегате приложения

7.1.

// creating instance
let controller = CustomViewController()

7.2.

// connecting view/xib with controller instance
let bundle = Bundle(for: type(of: controller))
bundle.loadNibNamed("CustomViewControllerView", owner: controller, options: nil)

7.3.

// get/set outlets
controller.labelOutlet.text = "title"
controller.imageOutlet.image = UIImage(named: "image1")

Ответ 16

Проверьте соединение IBOutlet, если оно связано с владельцем файла или представлением. Там могут быть ошибки.

Ответ 17

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

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

Ответ 18

Для меня у меня была такая же ошибка на локализованной раскадровке, элемент был добавлен в какой-то локаль, а не в другой, поэтому у меня была нулевая ссылка для этого элемента при переключении на отсутствующий локаль элемента, мне пришлось удалить (избыточное ) для этой раскадровки с помощью fooobar.com/questions/91864/....

Ответ 19

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

Вот мой код с Crash.

@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)
}

Ответ 20

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

Ответ 21

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

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

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

Ответ 22

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

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

Ответ 23

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

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

Ответ 24

  • выберите файлы .h и .m для просмотра файлов контроллера.
  • удалить ссылку этих файлов
  • повторно добавить файлы в дерево проекта
  • откройте раскадровку, в конечном итоге перестройте проект

Ответ 25

Я вижу, что вы используете ViewController!? в ViewController класс должен использовать -viewDidLoad, не -awakeFromNib, -awakeFromNib использовать для UIView class

Ответ 26

Несчастливо Я подклассифицировал свой контроллер представления AVPlayerViewController вместо UIViewController. Переигрывая его с UIViewController, все возвращается в нормальное состояние. Это должно помочь.

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

Ответ 27

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

override var nibName

и

override var nibBundle

методы.

После их удаления мои выходы начали работать.

Ответ 28

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

enter image description here

Ответ 29

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

Ответ 30

2019, ОДНА ВОЗМОЖНОСТЬ ЭТОЙ УЖАСНОЙ ПРОБЛЕМЫ:

  • Допустим, у вас есть вид контейнера, который показывает какие-то часы. Итак, у вас есть

    Класс Clock: UIViewController

Вы фактически используете его в нескольких местах в приложении.

На главном экране, на экране сведений, на экране редактирования.

У вас сложное современное приложение, похожее на Snapchat.

Фактически, Clock может быть загружен несколько раз в одно и то же время где-то на одном экране. (Может быть, это скрыто в некоторых случаях.)

Вы начинаете работать над одним экземпляром Clock на одной из ваших многочисленных раскадровок.

На этой раскадровке вы добавляете ярлык NewLabel.

Естественно вы добавляете розетку в код. Все должно работать. Все остальные магазины работают отлично.

Вы определенно связали розетку.

Но приложение вылетает с NewLabel равным нулю.

XCode четко говорит вам "вы забыли подключить розетку".

Причина в том, что.......... у вас есть "NewLabel" только на одном из вариантов использования раскадровки часов!

Сбой произошел из >> другого места & lt; & lt; & lt; & lt;, где вы используете Clock !!!!

Xcode не сообщает вам, что авария вообще из другого места, а не из того места, где вы работаете!

Авария на самом деле не из того места, где вы работаете, а из другой раскадровки, где на этой раскадровке нет элемента "NewLabel" !!!

Разочарование.