如何使用IBDesignable可视化情节提要中的可重用xib
在Zenchef,我们使用情节提要来设计视图控制器并获得应用程序导航的概述。
但是,情节提要板不适用于您要多次使用的视图。 例如,您可能想在UIViewController,UITableViewCell或UICollectionViewCell中使用复杂的视图。
为了避免每次都设计视图,通常有两种解决方案
1.以编程方式设计视图
这样,您可以使视图IBDesignable并通过实现prepareForInterfaceBuilder来实现,当您包括该视图时,您将在情节提要中看到结果。
当视图使用CoreGraphics实现drawRect时,它既简单又好用。
但是,一旦获得许多子视图,这将变得不切实际。 编码自动布局约束可能会很痛苦,大小类甚至更大。 Interface Builder功能强大,我们希望尽可能多地使用它。
2.在Xib中设计视图
这样,您就可以享受Interface Builder的所有功能,包括自动布局,尺寸分类和特征收集,同时保持视图的可重用性。
但是,每次需要时,都必须加载xib并以编程方式将视图添加到视图层次结构中。 此外,您也无法从“实时视图”(Xcode 6中引入)中受益。 您不会在情节提要中看到您的xib,因为在此阶段,所有IBOutlet都为零。 它将无法呈现,并且视图调试器将给您以下错误:
展开Optional值时意外发现nil
3.替代
因此,这是在情节提要中包括和可视化xib的方法:
步骤1 —创建一个视图容器
我们需要创建一个实用程序类,其行为类似于一个称为XibView的容器。
我们的XibView将负责加载xib,并将我们的视图添加为其子视图。
它具有2个属性:
- contentView将是您在xib中创建的视图。
- nibName是您的xib文件的标题。 我们希望稍后在情节提要中从身份检查器访问此字段。
@IBDesignable
XibView类:UIView {
var contentView:UIView?
@IBInspectable var nibName:String?
在初始化时,该类将:
- 从其xib名称加载视图
- 添加具有自动调整大小掩码的子视图,以实现自动布局约束
覆盖func awakeFromNib(){
super.awakeFromNib()
xibSetup()
}
func xibSetup(){
守卫let view = loadViewFromNib()else {return}
view.frame =界限
view.autoresizingMask =
[.flexibleWidth,.flexibleHeight]
addSubview(view)
contentView =视图
}
func loadViewFromNib()-> UIView? {
守卫let nibName = nibName else {return nil}
let bundle = Bundle(for:type(of:self))
设nib = UINib(nibName:nibName,bundle:bundle)
返回nib.instantiate(
withOwner:自我,
选项:无)。 UIView
}
第2步-设置xib的“文件所有者”
在您的xib中,使用您创建的实用程序类来设置文件的所有者。 在xib中不需要任何其他更改。
步骤3 —将Xib添加到情节提要
在情节提要中,当您要使用视图时,
- 将其类设置为XibView
- 在身份检查器中将其nibName属性设置为您的xib文件名
步骤4 —在情节提要中可视化xib
如您所见,您仍然无法在情节提要中可视化xib。 因此,编辑您的XibView并添加以下内容:
覆盖func prepareForInterfaceBuilder(){
super.prepareForInterfaceBuilder()
xibSetup()
contentView?.prepareForInterfaceBuilder()
}
这将实例化您先前看到的视图并触发IB渲染(确保它也是IBDesignable!)
最后
通过这种方式(重复步骤3),您可以轻松地将xib添加到情节提要中并将其视为实时视图。 这很简单。 它对您的代码没有太大影响。 它只是封装了您的视图。