2017-01-03 2 views
1

Я создаю приложение (в XCode 8.2.1), где некоторые объекты отображаются на двумерной доске, а когда пользователь удаляет один из этих объектов, должна отображаться информация об этом как о стиле модальной информационной панели. Мой дизайн заключается в том, чтобы информация была написана в отдельном контроллере представления, который я бы отобразил, когда это необходимо.Swift/iOS: IBOutlet nil после загрузки контроллера просмотра

Я разработал базовый заглушку для второго контроллера представления и добавил в него ярлык в построителе интерфейса. Тогда Я Ctrl-сшитый этот ярлык на мой пользовательский класс VC:

class InfoViewController: UIViewController { 
    @IBOutlet weak var info: UILabel! 
    override func viewDidLoad() { 
     super.viewDidLoad() 
    } 
    func displayInfo() { 
     info.attributedText = NSAttributedString(string: "abc") 
    } 
} 

Однако, когда я проверить мое приложение и нажмите на объект, то info поле nil даже в viewDidLoad() метод моего пользовательского класса VC. То, как я уверен, отображение моего VC выглядит следующим образом:

let infoViewController = InfoViewController() 
infoViewController.modalPresentationStyle = .overCurrentContext 
self.present(infoViewController, animated: true, completion: nil) 
infoViewController.displayInfo() 

(Примечание: В конце концов, у меня будет только один единственный экземпляр InfoViewController, но это только для тестирования я не ожидаю, имея глобальный экземпляр. будет никакой разницы?)

Как я уже говорил, будь то внутри метода viewDidLoad() или в методе displayInfo(), info всегда nil, таким образом, что установка его атрибут attributedString сбой приложения. Думать, что метод present можно назвать асинхронным, я попытался позвонить displayInfo() изнутри viewDidLoad(), но это не имело никакого значения.

Может ли кто-нибудь сказать мне то, что я забыл, что позволило бы корректно инициализировать мой IBOutlet?

Спасибо!

Дэвид

+1

Проблема заключается в том, что вы выполнили 'InfoViewController()', создавая экземпляр контроллера просмотра независимо от любой сцены раскадровки. Вы хотите использовать ['storyboard.instantiateViewController'] (https://developer.apple.com/reference/uikit/uistoryboard/1616214-instantiateviewcontroller). – Rob

+0

Вы используете раскадровку? если да, то я предполагаю, что вы должны получить 'InfoViewController' из раскадровки, а не путем создания нового экземпляра ... –

ответ

5

Проблема в том, ссылка на InfoViewController(), который инициализирует контроллер представления независимо от любого раскадровку сцены. Вы хотите использовать instantiateViewController:

let infoViewController = storyboard?.instantiateViewController(withIdentifier: "Info") as! InfoViewController 
infoViewController.modalPresentationStyle = .overCurrentContext 
present(infoViewController, animated: true) { 
    infoViewController.displayInfo() 
} 

Несколько примечаний:

  • Это предполагает, что (а) вы дали сцену в раскадровке «раскадровка ид»; (b) вы установили базовый класс для этой сцены на InfoViewController.

  • Обратите внимание, что я вызвал displayInfo в обработчике завершения present, потому что вы, вероятно, не хотите, чтобы это вызывалось до тех пор, пока сцена не была представлена, а розетки были подключены.


В качестве альтернативы, вы можете обновить, не выходные свойства InfoViewController сразу после инстанцировании его и затем его viewDidLoad принять эти свойства и обновления точек, например:

class InfoViewController: UIViewController { 
    var info: String! 
    @IBOutlet weak var infoLabel: UILabel! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     infoLabel.attributedText = NSAttributedString(string: info) 
    } 
} 

Примечание, Я изменил имя @IBOutlet на infoLabel и добавил String имущество под названием info.Это, как правило, соглашение, что в выходах есть некоторый суффикс, указывающий тип управления, а объекты модели, такие как свойство String, не имеют суффикса. (. Вы просто хотите, чтобы убедиться, что вы удалите эту старую розетку в инспекторе соединений в IB, так что у вас нет проблем с этими изменениями имени свойства)

Во всяком случае, вы можете сделать:

let infoViewController = storyboard?.instantiateViewController(withIdentifier: "Info") as! InfoViewController 
infoViewController.info = "abc" 
infoViewController.modalPresentationStyle = .overCurrentContext 
present(infoViewController, animated: true, completion: nil) 

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

+0

Большое спасибо! Я думал, что вызов 'self.present' будет выполнять необходимую связь с раскадрой. – David

0

Я Заменено

let vc = CCDetailViewController() 

С

let vc = self.storyboard?.instantiateViewController(withIdentifier: "CCDetailViewController") 

Наконец

self.present(vc!, animated: true, completion: nil) 

Теперь это работает ...

Смежные вопросы