Загрузка ViewController из файла xib
У меня были MyViewController.swift
и MyViewController.xib
, представляющие макет MyViewController.
Я попробовал разные методы для загрузки этого контроллера представления, включая:
//1
let myVC = UINib(nibName: "MyViewController", bundle:
nil).instantiateWithOwner(nil, options: nil)[0] as? MyViewController
//2
let myVC = NSBundle.mainBundle().loadNibNamed("MyViewController", owner: self, options: nil)[0] as? MyViewController
//3
let myVC = MyViewController(nibName: "MyViewController", bundle: nil)
Третий - единственная успешная инициализация, но предыдущие два вызывают ошибку:
Завершение приложения из-за неперехваченного исключения "NSUnknownKeyException",
reason: '[setValue: forUndefinedKey:]: это класс не соответствует ключевому значению для ключа XXX.
Что не так с этими методами загрузки?
Ответы
Ответ 1
Swift 3
let myViewController = MyViewController(nibName: "MyViewController", bundle: nil)
self.present(myViewController, animated: true, completion: nil)
или нажмите навигационный контроллер
self.navigationController!.pushViewController(MyViewController(nibName: "MyViewController", bundle: nil), animated: true)
Ответ 2
![File's Owner]()
Обратите внимание на File Owner
. В вашем случае File Owner
должен быть MyViewController
или его sub-class
.
И следующие коды, если он выполняется в классе Foo
.
// If 'self' is an instance of 'Foo' class.
// In this case, 'File Owner' will be a 'Foo' instance due to 'self' parameter.
let myVC = NSBundle.mainBundle().loadNibNamed("MyViewController", owner: self, options: nil)[0] as? MyViewController
Он назначает self
как owner
. Таким образом, File Owner
является Foo
, а не MyViewController
. Тогда для класса Foo
эти IBOutlet
не могут быть подключены к Foo
. Итак, это исключение.
Ответ 3
extension UIViewController {
static func loadFromNib() -> Self {
func instantiateFromNib<T: UIViewController>() -> T {
return T.init(nibName: String(describing: T.self), bundle: nil)
}
return instantiateFromNib()
}
}
Используйте это как следующее: -
let testVC = TestVC.loadFromNib()
Ответ 4
Проблема не в методах... вы, вероятно, сохранили выход (XXX), подключенный для некоторого uielement, и удалили его из соответствующего контроллера... Я добавляю пример ниже... ![введите описание изображения здесь]()
вышеуказанная кнопка подключается к контроллеру, но когда я комментирую выход
![введите описание изображения здесь]()
Мое приложение падает
![введите описание изображения здесь]()
![введите описание изображения здесь]()
попробуйте найти выход (xxx), отсутствующий в viewcontroller, но находится в файле xib. Упование помогает:)
Ответ 5
У меня была та же проблема. Созданный автоматически xib имел UIView. Вы должны удалить представление, добавить новый контроллер представления в xib, установить класс контроллера представления в тот, который вы хотите, а затем подключить выходы. После этого вы можете использовать приведенные выше коды, чтобы получить экземпляр этого контроллера вида, например:
if let menuVC = Bundle.main.loadNibNamed("MenuViewController", owner: nil, options: nil)?.first as? MenuViewController {
menuVC.profileType = profileType
vc.present(menuVC, animated: true, completion: nil)
}
Ответ 6
@AechoLiu ответ отличный. У меня был тот же вопрос, и я ответил на него с помощью приведенного ниже исправления.
Проблема:
let vc1 = NSViewController(nibName: YDNibIdentifier.myplainvc, bundle: nil)
Fix:
let vc1 = MyPlainViewController(nibName: YDNibIdentifier.myplainvc, bundle: nil)
Я случайно привел свой Nib файл к неправильному Clas (NSViewController), несмотря на то, что он правильно подключен внутри .xib файла.
Ответ 7
Попробуйте ввести код,
//1
let nib = UINib(nibName: "MyViewController", bundle:nil)
myVC = nib.instantiateWithOwner(self, options: nil)[0] as? MyViewController
ИЛИ
myVC = nib.instantiateWithOwner(self, options: nil).first as? MyViewController
//2
let nib : NSArray = NSBundle.mainBundle().loadNibNamed("MyViewController", owner: self, options: nil)
myVC = nib.objectAtIndex(0) as? MyViewController
Это будет работать.