当我点击没有导航的按钮时,如何在 xib(ViewController) 中打开 xib(ViewController)
How can I open xib(ViewController) in xib(ViewController) when I tap Button without Navigation
我没有使用故事板。
我制作了自定义TabBarView。 (我在视图上添加了 2 个按钮)。
我连接了具有相同功能的按钮,并给了按钮一个 tag
值。
如何在按下第一个按钮或任意按钮时打开ViewController?
当我点击第一个按钮时出现此错误。
错误:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x28184c020> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key countryListTableView.'
terminating with uncaught exception of type NSException
场景代理:
guard let windowScene = (scene as? UIWindowScene) else { return }
let countryRouter = TabBarViewController()
let window = UIWindow(windowScene: windowScene)
window.rootViewController = countryRouter
self.window = window
window.makeKeyAndVisible()
ViewController国家/地区列表:
class ViewControllerCountryList: UIViewController, CountryListModule.View {
.
.
.
}
TabBarButton:
class TabBarViewController: UIViewController {
@IBOutlet weak var contentView: UIView!
@IBOutlet weak var tabBarView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
designableTabBarView()
}
private func designableTabBarView() {
tabBarView.layer.cornerRadius = tabBarView.frame.size.height / 3
tabBarView.clipsToBounds = true
}
@IBAction func onClickTabBarButton(_ sender: UIButton) {
switch sender.tag {
case 1:
let nib = UINib(nibName: "ViewControllerCountryList", bundle: nil)
guard let countryListVC = nib.instantiate(withOwner: nil, options: nil).first as? ViewControllerCountryList else { return }
self.addChild(countryListVC)
countryList.didMove(toParent: self)
default:
break
}
}
}
错误是说您加载了一个 NSObject
并试图像它有一个 countryListTableView
成员一样使用它。这表明您的 xib 中的第一项不是 ViewControllerCountryList
.
如果查看 xib 没有找到明显的解决方案,我建议通过检查加载 xib 时实际返回的内容(而不是立即尝试转换它)来进行调试。
使用 instantiate(withOwner:options:)
不太适合您的任务。
更好的方法是使用init(nibName:bundle:)
。
此扩展将其包装成一个简单的单线调用:
extension UIViewController {
static func loadFromNib() -> Self {
func instantiateFromNib<T: UIViewController>() -> T {
return T.init(nibName: String(describing: T.self), bundle: nil)
}
return instantiateFromNib()
}
}
有了它,您现在可以:
let countryListVC = ViewControllerCountryList.loadFromNib()
对于您的“自定义选项卡”布局,请看一下:
class TabBarViewController: UIViewController {
@IBOutlet weak var contentView: UIView!
@IBOutlet weak var tabBarView: UIView!
// keep references to the loaded view controllers
var countryListVC: ViewControllerCountryList!
var someOtherVC: SomeOtherViewController!
override func viewDidLoad() {
super.viewDidLoad()
designableTabBarView()
}
private func designableTabBarView() {
tabBarView.layer.cornerRadius = tabBarView.frame.size.height / 3
tabBarView.clipsToBounds = true
}
@IBAction func onClickTabBarButton(_ sender: UIButton) {
switch sender.tag {
case 1:
// remove other VC view from content view
if someOtherVC != nil {
someOtherVC.view.removeFromSuperview()
}
// if we haven't loaded ViewControllerCountryList yet
if countryListVC == nil {
countryListVC = ViewControllerCountryList.loadFromNib()
self.addChild(countryListVC)
contentView.addSubview(countryListVC.view)
countryListVC.didMove(toParent: self)
}
// add ViewControllerCountryList view to contentView
contentView.addSubview(countryListVC.view)
countryListVC.view.frame = contentView.bounds
countryListVC.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
case 2:
// remove country list VC view from content view
if countryListVC != nil {
countryListVC.view.removeFromSuperview()
}
// if we haven't loaded SomeOtherViewController yet
if someOtherVC == nil {
someOtherVC = SomeOtherViewController.loadFromNib()
self.addChild(someOtherVC)
contentView.addSubview(someOtherVC.view)
someOtherVC.didMove(toParent: self)
}
// add SomeOtherViewController view to contentView
contentView.addSubview(someOtherVC.view)
someOtherVC.view.frame = contentView.bounds
someOtherVC.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
default:
break
}
}
}
我没有使用故事板。
我制作了自定义TabBarView。 (我在视图上添加了 2 个按钮)。
我连接了具有相同功能的按钮,并给了按钮一个 tag
值。
如何在按下第一个按钮或任意按钮时打开ViewController?
当我点击第一个按钮时出现此错误。
错误:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSObject 0x28184c020> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key countryListTableView.'
terminating with uncaught exception of type NSException
场景代理:
guard let windowScene = (scene as? UIWindowScene) else { return }
let countryRouter = TabBarViewController()
let window = UIWindow(windowScene: windowScene)
window.rootViewController = countryRouter
self.window = window
window.makeKeyAndVisible()
ViewController国家/地区列表:
class ViewControllerCountryList: UIViewController, CountryListModule.View {
.
.
.
}
TabBarButton:
class TabBarViewController: UIViewController {
@IBOutlet weak var contentView: UIView!
@IBOutlet weak var tabBarView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
designableTabBarView()
}
private func designableTabBarView() {
tabBarView.layer.cornerRadius = tabBarView.frame.size.height / 3
tabBarView.clipsToBounds = true
}
@IBAction func onClickTabBarButton(_ sender: UIButton) {
switch sender.tag {
case 1:
let nib = UINib(nibName: "ViewControllerCountryList", bundle: nil)
guard let countryListVC = nib.instantiate(withOwner: nil, options: nil).first as? ViewControllerCountryList else { return }
self.addChild(countryListVC)
countryList.didMove(toParent: self)
default:
break
}
}
}
错误是说您加载了一个 NSObject
并试图像它有一个 countryListTableView
成员一样使用它。这表明您的 xib 中的第一项不是 ViewControllerCountryList
.
如果查看 xib 没有找到明显的解决方案,我建议通过检查加载 xib 时实际返回的内容(而不是立即尝试转换它)来进行调试。
使用 instantiate(withOwner:options:)
不太适合您的任务。
更好的方法是使用init(nibName:bundle:)
。
此扩展将其包装成一个简单的单线调用:
extension UIViewController {
static func loadFromNib() -> Self {
func instantiateFromNib<T: UIViewController>() -> T {
return T.init(nibName: String(describing: T.self), bundle: nil)
}
return instantiateFromNib()
}
}
有了它,您现在可以:
let countryListVC = ViewControllerCountryList.loadFromNib()
对于您的“自定义选项卡”布局,请看一下:
class TabBarViewController: UIViewController {
@IBOutlet weak var contentView: UIView!
@IBOutlet weak var tabBarView: UIView!
// keep references to the loaded view controllers
var countryListVC: ViewControllerCountryList!
var someOtherVC: SomeOtherViewController!
override func viewDidLoad() {
super.viewDidLoad()
designableTabBarView()
}
private func designableTabBarView() {
tabBarView.layer.cornerRadius = tabBarView.frame.size.height / 3
tabBarView.clipsToBounds = true
}
@IBAction func onClickTabBarButton(_ sender: UIButton) {
switch sender.tag {
case 1:
// remove other VC view from content view
if someOtherVC != nil {
someOtherVC.view.removeFromSuperview()
}
// if we haven't loaded ViewControllerCountryList yet
if countryListVC == nil {
countryListVC = ViewControllerCountryList.loadFromNib()
self.addChild(countryListVC)
contentView.addSubview(countryListVC.view)
countryListVC.didMove(toParent: self)
}
// add ViewControllerCountryList view to contentView
contentView.addSubview(countryListVC.view)
countryListVC.view.frame = contentView.bounds
countryListVC.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
case 2:
// remove country list VC view from content view
if countryListVC != nil {
countryListVC.view.removeFromSuperview()
}
// if we haven't loaded SomeOtherViewController yet
if someOtherVC == nil {
someOtherVC = SomeOtherViewController.loadFromNib()
self.addChild(someOtherVC)
contentView.addSubview(someOtherVC.view)
someOtherVC.didMove(toParent: self)
}
// add SomeOtherViewController view to contentView
contentView.addSubview(someOtherVC.view)
someOtherVC.view.frame = contentView.bounds
someOtherVC.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
default:
break
}
}
}