[英]How to Initialize UIViews and UIViewControllers Using Protocols in Swift
I've been experimenting lately with building iOS views using a trick I learned from René Cacheaux to easily initialize UIViewControllers from code: 我最近一直在尝试使用从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")
}
}
You can then inherit from NiblessViewController
in your custom view controller classes without having do the initializer overriding each time: 然后,您可以在自定义视图控制器类中从
NiblessViewController
继承,而不必每次都进行初始化覆盖:
class CustomViewController: NiblessViewController {
// ...
}
This works great when working with a vanilla UIViewController
, but I can't figure out a nice way to use it with other view controller classes (eg UITableViewController
, UINavigationController
) without creating a separate Nibless
class for each view controller type (eg NiblessTableViewController
, NiblessNavigationController
), containing the exact same code. 在使用普通
UIViewController
,此方法效果很好,但我无法找到一种与其他视图控制器类(例如UITableViewController
, UINavigationController
)一起使用的好方法,而无需为每种视图控制器类型(例如NiblessTableViewController
, NiblessNavigationController
)创建单独的Nibless
类),包含完全相同的代码。
One thing I tried was to use a protocol extension like so: 我尝试过的一件事是使用这样的协议扩展:
protocol Nibless {}
extension Nibless where Self: UIViewController {
// Same initialization code as above
}
Doing it this way, I get three errors saying: 这样,我会遇到三个错误:
- 'super' cannot be used outside of class members
'super'不能在班级成员之外使用
- 'required' initializer in non-class type 'NiblessViewController'
非类类型“ NiblessViewController”中的“必需”初始化程序
- initializer does not override a designated initializer from its superclass
初始化程序不会覆盖其父类中的指定初始化程序
Any ideas on a nice way to do this without having duplicate code? 在没有重复代码的情况下,有什么好主意吗?
I totally get why you are going after what you are (to forbid IB), but it's not possible at the moment. 我完全理解为什么您要追求自己的身份(禁止IB),但目前尚不可能。 It's also not super practical either.
这也不是超级实用。 Let me explain:
让我解释:
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
method is the class's designated initializer. init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
方法是该类的指定初始化程序。 You should use this whenever initializing a UIViewController
and marking it unavailable isn't the proper behavior. UIViewController
并将其标记为不正确时,都应使用此方法。 UIViewController
they each have their own initializers (like UITableViewController(style:)
), which wouldn't be covered in your protocol. UIViewController
其他子类,每个子类都有自己的初始化程序(如UITableViewController(style:)
),但协议中不会涉及它们。 @objc
protocols, and in my brief testing with a playground didn't work like I was hoping it would (that would be very cool if we could do it though). @objc
协议标记为不可用,并且在我的操场上进行的简短测试无法像我希望的那样工作(如果可以的话,那将非常酷)。 I think your best bet might be to make your own "base" subclasses of each UIViewController
subclass that you want and expressly forbid IB there. 我认为最好的选择是为每个
UIViewController
子类创建自己的“基本”子类,并在那里明确禁止IB。 One of the nice things about initialization in code is that you can get rid of Optional<T>
properties that have to litter IB-bound view controllers. 关于代码初始化的好处之一是,您可以摆脱
Optional<T>
属性,这些属性必须乱扔IB绑定的视图控制器。
Here's a gist that I created which has the base UIViewController
subclass. 这是我创建的要点,它具有基本的
UIViewController
子类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.