原始解决方案
- 我创建了一个XIB和一个名为SomeView的类(为方便起见,使用了相同的名称)。我都基于UIView。
- 在XIB中,我将“文件所有者”类更改为SomeView(在身份检查器中)。
- 我在SomeView.swift中创建了一个UIView出口,将其链接到XIB文件中的顶级视图(为方便起见,将其命名为“视图”)。然后,根据需要将其他插座添加到XIB文件中的其他控件。
- 在SomeView.swift中,我将XIB加载到“使用代码初始化”初始化程序中。无需为“自己”分配任何内容。加载XIB后,所有插座都将连接,包括顶层视图。唯一缺少的是将顶视图添加到视图层次结构中:
。
class SomeView: UIView { required init(prer aDeprer: NSCoder) { super.init(prer: aDeprer) NSBundle.mainBundle().loadNibNamed("SomeView", owner: self, options: nil) self.addSubview(self.view); // adding the top level view to the view hierarchy } ...}请注意,通过这种方式,我得到了一个从笔尖加载自身的类。然后,只要可以在项目中使用UIView(在界面生成器中或以编程方式),就可以将SomeView用作类。
更新-使用Swift 3语法
在以下扩展中加载xib是作为一种实例方法编写的,然后可以由上面的初始化程序使用:
extension UIView { @discardableResult // 1 func fromNib<T : UIView>() -> T? { // 2 guard let contentView = Bundle(for: type(of: self)).loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as? T else { // 3 // xib not loaded, or its top view is of the wrong type return nil } self.addSubview(contentView) // 4 contentView.translatesAutoresizingMaskIntoConstraints = false // 5 contentView.layoutAttachAll(to: self) // 6 return contentView // 7 }}- 使用可丢弃的返回值,因为当所有插座都已连接时,调用者对返回的视图几乎没有兴趣。
- 这是一个通用方法,它返回类型为UIView的可选对象。如果无法加载视图,则返回nil。
- 尝试以与当前类实例相同的名称加载XIB文件。如果失败,则返回nil。
- 将顶级视图添加到视图层次结构。
- 此行假定我们正在使用约束来布局视图。
- 此方法增加了顶部,底部,前导和尾随约束-将视图在所有侧面附加到“自身”
- 返回顶层视图
调用方方法可能如下所示:
final class SomeView: UIView { // 1. required init?(prer aDeprer: NSCoder) { // 2 - storyboard initializer super.init(prer: aDeprer) fromNib() // 5. } init() { // 3 - programmatic initializer super.init(frame: CGRect.zero) // 4. fromNib() // 6. } // other methods ...}- SomeClass是一个UIView子类,可从SomeClass.xib文件加载其内容。“最终”关键字是可选的。
- 用于在情节提要中使用视图的初始化程序(请记住,将SomeClass用作情节提要视图的自定义类)。
- 用于以编程方式创建视图时的初始化程序(即:“ let myView = SomeView()”)。
- 使用全零帧,因为此视图是使用自动布局进行布局的。请注意,“ init(frame:CGRect){..}”方法不是独立创建的,因为自动布局仅在我们的项目中使用。
- &6.使用扩展名加载xib文件。
信用:在此解决方案中使用通用扩展名的灵感来自以下罗伯特的回答。
编辑 将“视图”更改为“ contentView”以避免混淆。还将数组下标更改为“ .first”。



