我最近一直在尝试使用从René Cacheaux学到的技巧来构建iOS视图,以便从代码中轻松初始化UIViewControllers:
class NiblessViewController: UIViewController {
init() {
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable, message: "Loading this view controller from a nib is unsupported.")
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
@available(*, unavailable, message: "Loading this view controller from a nib is unsupported.")
required init?(coder aDecoder: NSCoder) {
fatalError("Loading this view controller from a nib is unsupported")
}
}
然后,您可以在自定义视图控制器类中继承NiblessViewController
,而无需每次都执行初始化程序覆盖:
class CustomViewController: NiblessViewController {
// ...
}
使用vanilla UIViewController
时这很有用,但我无法找到一种很好的方法将它与其他视图控制器类(例如UITableViewController
,UINavigationController
)一起使用为每个视图控制器类型创建单独的Nibless
类(例如NiblessTableViewController
,NiblessNavigationController
),包含完全相同的代码。
我尝试的一件事是使用协议扩展,如下所示:
protocol Nibless {}
extension Nibless where Self: UIViewController {
// Same initialization code as above
}
这样做,我得到三个错误:
- 'super'不能在班级成员之外使用
- 非必要类型'NiblessViewController'中的'required'初始值设定项
- 初始化程序不会覆盖其超类
中的指定初始值设定项 醇>
在没有重复代码的情况下,有什么好的方法可以做到这一点吗?
答案 0 :(得分:3)
我完全明白为什么你正在追求自己(禁止IB),但目前还不可能。它也不是超实用的。让我解释一下:
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
方法是类的指定初始值设定项。每当初始化UIViewController
并将其标记为不可用时,您应该使用此方法。UIViewController
的其他子类,它们每个都有自己的初始值设定项(如UITableViewController(style:)
),这些都不在您的协议中。@objc
协议,并且我在游乐场的简短测试中没有像我希望的那样工作(如果我们可以做到这样会很酷) )。我认为你最好的选择可能是创建你想要的每个UIViewController
子类的自己的“基础”子类,并明确禁止IB。关于代码初始化的一个好处是,您可以摆脱必须丢弃IB绑定视图控制器的Optional<T>
属性。
Here's a gist that I created which has the base UIViewController
subclass.