我有一个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',
而终止应用原因:'[setValue:forUndefinedKey:]:this class不是键码XXX的键值编码。
这些加载方法有什么问题?
答案 0 :(得分:62)
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)
答案 1 :(得分:11)
注意File's Owner
。在您的情况下,File's Owner
必须为MyViewController
,或sub-class
。
以下代码,如果它在类Foo
中执行。
// If `self` is an instance of `Foo` class.
// In this case, `File's 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's Owner
为Foo
,而不是MyViewController
。然后,对于Foo
课程,这些IBOutlet
无法连接到Foo
。所以,它会抛出异常。
答案 2 :(得分:2)
问题不在于方法......你可能已经为一些uielement连接了一个插座(XXX)并将其从相应的控制器中删除了......我在下面添加了例子...... < / p>
所以尽量找到viewcontroller中缺少的outlet(xxx)但是在xib文件中。希望它有帮助:)
答案 3 :(得分:2)
我遇到了同样的问题。自动生成的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)
}
答案 4 :(得分:2)
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()
答案 5 :(得分:0)
@AechoLiu的回答很好。我有相同的问题,并使用以下修复程序予以回答。
问题:
let vc1 = NSViewController(nibName: YDNibIdentifier.myplainvc, bundle: nil)
修复:
let vc1 = MyPlainViewController(nibName: YDNibIdentifier.myplainvc, bundle: nil)
尽管我已将Nib文件正确连接到.xib文件中,但还是意外地将其Nib文件转换为错误的Clas(NSViewController)。
答案 6 :(得分:0)
已为Swift 5更新
let myVC = Bundle.main.loadNibNamed("MyViewController", owner: self, options: nil)![0] as? MyViewController
答案 7 :(得分:0)
将UIButton
与@IBAction
连接起来,并将以下代码添加到action方法中,以显示在.xib文件中设置的新UIViewController
。
@IBAction func handleButtonAction(_ sender: UIButton) {
let viewControllerInXib = ViewControllerInXib(nibName: "ViewControllerXibName", bundle: nil)
present(viewControllerInXib, animated: true)
}
要通过UINavigationController
进行导航,您应该使用以下方法:
@IBAction func handleButtonAction(_ sender: UIButton) {
let viewControllerInXib = ViewControllerInXib(nibName: "ViewControllerXibName", bundle: nil)
if let navigationController = navigationController {
navigationController.pushViewController(viewControllerInXib, animated: true)
} else {
print("Navigation controller unavailable! Use present method.")
}
}
答案 8 :(得分:0)
public extension UIViewController {
static func loadNib() -> Self {
func instantiateFromNib<T: UIViewController>() -> T {
return T.init(nibName: String(describing: T.self), bundle: Bundle.init(for: Self.self))
}
return instantiateFromNib()
}
}
答案 9 :(得分:0)
这个扩展功能对我不起作用。
static func loadFromNib() -> Self {
func instantiateFromNib<T: UIViewController>() -> T {
return T.init(nibName: String(describing: T.self), bundle: nil)
}
return instantiateFromNib()
}
它把我扔了
<块引用>无法在包中加载 NIB:'NSBundle ... with name 'UIViewController'
所以,我把它改成了这个并让它工作了。
static func instantiateFromNib<T: UIViewController>() -> T {
// It is going to return YourAppName.YourClassName
let classDescription = classForCoder().description()
// Replacing YourAppName with Empty string
let nibFileName = classDescription.replacingOccurrences(of: "\(Bundle.main.infoDictionary?["CFBundleName"] as! String).", with: String())
return T.init(nibName: nibFileName, bundle: Bundle.init(for: Self.self))
}
请记住,您的 .xib
文件和 .swift
类名应该相同才能正常工作。
答案 10 :(得分:-1)
尝试以下代码,
// 1
let nib = UINib(nibName: "MyViewController", bundle:nil)
myVC = nib.instantiateWithOwner(self, options: nil)[0] as? MyViewController
OR
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
这样可行。
答案 11 :(得分:-1)
我删除了文件所有者的类名,并将其设置为第一个视图的类名。然后,我必须为要使用的组件设置插座。
然后我像
let myViewController = Bundle.main.loadNibNamed("MyViewController", owner: self, options: nil)?.first as! MyViewController
view.addSubview(myViewController)
答案 12 :(得分:-2)
在 Swift5 中使用
self.navigationController!.pushViewController(MyViewController(nibName: "MyViewController", bundle: nil), animation: true)