如何使用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添加到情节提要中并将其视为实时视图。 这很简单。 它对您的代码没有太大影响。 它只是封装了您的视图。