[英]Loading a custom UIView from a XIB file within a XIB for a ViewController view
[英]Loading ViewController from xib file
我有一個MyViewController.swift
和一個MyViewController.xib
展示MyViewController.xib
的布局。
我嘗試了不同的方法來加載這個視圖控制器,包括:
//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:]: 此類不是密鑰 XXX 的密鑰值編碼兼容。
這些加載方法有什么問題?
斯威夫特 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)
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()
注意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 the `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
。 所以,它拋出異常。
我有同樣的問題。 自動生成的 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)
}
試試下面的代碼,
//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
這將起作用。
@AechoLiu 的回答很棒。 我有同樣的問題,並通過以下修復回答了它。
問題:
let vc1 = NSViewController(nibName: YDNibIdentifier.myplainvc, bundle: nil)
修復:
let vc1 = MyPlainViewController(nibName: YDNibIdentifier.myplainvc, bundle: nil)
我不小心將我的 Nib 文件轉換為錯誤的 Clas ( NSViewController ),盡管它在 .xib 文件中正確連接。
為 Swift 5 更新
let myVC = Bundle.main.loadNibNamed("MyViewController", owner: self, options: nil)![0] as? MyViewController
將UIButton
與@IBAction
連接@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.")
}
}
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()
}
}
這個擴展功能對我不起作用。
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
類的名稱應該是相同的,它的工作。
你可以使用這個小的 UIViewController 擴展
extension UIViewController {
class func loadController() -> Self {
return Self(nibName: String(describing: self), bundle: nil)
//Or You can use this as well
//Self.init(nibName: String(describing: self), bundle: nil)
}
}
像這樣使用
let controller = CustomViewController.loadController()
我刪除了文件所有者的類名並將其設置為第一個視圖的類名。 然后我必須為我將要使用的組件設置出口。
然后我加載了那個視圖類
let myViewController = Bundle.main.loadNibNamed("MyViewController", owner: self, options: nil)?.first as! MyViewController
view.addSubview(myViewController)
在 Swift5 中工作
self.navigationController!.pushViewController(MyViewController(nibName: "MyViewController", bundle: nil), 動畫: true)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.