在故事板中重用uiview xib

Gar*_*gle 74 interface-builder xib uiview uistoryboard autolayout

我通常喜欢在界面构建器中创建和设计我的uiviews.有时我需要在xib中创建一个可以在故事板中的多个视图控制器中重用的视图.

Gar*_*gle 126

在故事板中重用和渲染xib.

使用Swift 2.2和Xcode 7.3.1进行测试

1 ----创建一个名为'DesignableXibView'的新UIView

  • 文件>新建>文件>来源> Cocoa Touch Class> UIView

2 ----创建一个名为'DesignableXibView'的匹配xib文件

  • 文件>新建>文件>用户界面>查看

3 ----设置xib的文件所有者

  1. 选择xib
  2. 选择文件的所有者
  3. 在Identity Inspector中将自定义类设置为"DesignableXibView".

将Xib的所有者设置为自定义类

  • 注意:不要在xib上设置视图的自定义类.只有文件所有者!

4 ---- DesignableXibView的实现

//  DesignableXibView.swift

import UIKit

@IBDesignable

class DesignableXibView: UIView {

    var contentView : UIView?

    override init(frame: CGRect) {
        super.init(frame: frame)
        xibSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        xibSetup()
    }

    func xibSetup() {
        contentView = loadViewFromNib()

        // use bounds not frame or it'll be offset
        contentView!.frame = bounds

        // Make the view stretch with containing view
        contentView!.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]

        // Adding custom subview on top of our view (over any custom drawing > see note below)
        addSubview(contentView!)
    }

    func loadViewFromNib() -> UIView! {

        let bundle = NSBundle(forClass: self.dynamicType)
        let nib = UINib(nibName: String(self.dynamicType), bundle: bundle)
        let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView

        return view
    }

}
Run Code Online (Sandbox Code Playgroud)

5 ----在故事板中测试可重复使用的视图

  1. 打开你的故事板
  2. 添加视图
  3. 设置该视图的自定义类
  4. 等一下......好吧!

在故事板视图控制器内部进行Xib渲染

  • 我也没有在界面构建器中看到预览.Xcode 9 (8认同)
  • 我回答了自己的问题,在我阅读这些SO文章说要设置文件所有者而不是视图之前,看起来我设置了出口.它在我断开所有插座后确保文件所有者是正确的,然后重新添加所有插座. (3认同)
  • 设置文件所有者与自定义类之间有什么区别? (2认同)
  • 代码在运行时有效,但在我的Xcode 9中,它在模块行下显示"Designable build failed" (2认同)

Gar*_*gle 73

新!更新的答案能够直接在故事板中呈现(和swift!)

适用于Xcode 6.3.1

创建一个名为"ReuseableView"的新UIView

  • 文件>新建>文件>来源> Cocoa Touch Class> UIView

创建一个名为"ReuseableView"的匹配xib文件

  • 文件>新建>文件>用户界面>查看

设置xib的文件所有者

  1. 选择xib
  2. 选择文件的所有者
  3. 在Identity Inspector中将自定义类设置为"ReusableView". 在此输入图像描述

    • 注意:不要在xib上设置视图的自定义类.只有文件所有者!

从ReuseableView.xib中的视图到ReuseableView.h接口创建一个出口

  1. 打开助理编辑器
  2. 控制+从视图拖动到您的界面

在此输入图像描述

添加initWithCoder实现以加载视图并添加为子视图.

- (id)initWithCoder:(NSCoder *)aDecoder{
    self = [super initWithCoder:aDecoder];
    if (self) {

        // 1. load the interface
        [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
        // 2. add as subview
        [self addSubview:self.view];
        // 3. allow for autolayout
        self.view.translatesAutoresizingMaskIntoConstraints = NO;
        // 4. add constraints to span entire view
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[view]|" options:0 metrics:nil views:@{@"view":self.view}]];
        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[view]|" options:0 metrics:nil views:@{@"view":self.view}]];

    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

在故事板中测试可重复使用的视图

  1. 打开你的故事板
  2. 添加视图
  3. 设置该视图的自定义类

在此输入图像描述

跑,观察! 在此输入图像描述

  • @ andres.cianio但是你必须采取完全不同的方法.您必须以编程方式构建视图并使用IBDesignable指令.这是专门为想要在视觉上构建视图的人们而设计的.我不知道如何在xib中直观地构建视图并将其呈现在故事板中.如果不是这样的话,我很快就会感到惊讶. (2认同)
  • 很棒的解释!但是我有一个提示:使用`UINib(nibName:nibName,bundle:nil).instantiateWithOwner(nil,options:nil)`这比NSBundle-Version快. (2认同)

har*_*h_v 48

Swift 3&4更新为已接受的答案

1.创建一个名为'DesignableXibView'的新UIView

  • 文件>新建>文件>来源> Cocoa Touch Class> UIView

2.创建名为"DesignableXibView"的匹配xib文件

  • 文件>新建>文件>用户界面>查看

3.设置xib的文件所有者

选择"DesignableXibView.xib">"文件所有者">在Identity Inspector中将"Custom Class"设置为"DesignableXibView".

  • 注意:不要在xib上设置视图的自定义类.只有文件所有者!

4. DesignableXibView的实现

    import UIKit

@IBDesignable

class DesignableXibView: UIView {

    var contentView : UIView!

    override init(frame: CGRect) {
        super.init(frame: frame)
        xibSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        xibSetup()
    }

    func xibSetup() {
        contentView = loadViewFromNib()

        // use bounds not frame or it'll be offset
        contentView.frame = bounds

        // Make the view stretch with containing view
        contentView.autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]

        // Adding custom subview on top of our view 
        addSubview(contentView)
    }

    func loadViewFromNib() -> UIView! {

        let bundle = Bundle(for: type(of: self))
        let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
        let view = nib.instantiate(withOwner: self, options: nil).first as! UIView

        return view
    }
} 
Run Code Online (Sandbox Code Playgroud)

5在故事板中测试可重用的视图

  • 打开你的故事板

  • 添加视图

  • 设置该视图的自定义类

  • 我无法在Xcode8/Swift3中使用它.在运行应用程序时工作正常但在故事板中不显示. (2认同)

Ank*_*oel 11

swift 2中的initWithCoder函数,如果有人在翻译时遇到问题:

required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        UINib(nibName: String(self.dynamicType), bundle: NSBundle.mainBundle()).instantiateWithOwner(self, options: nil)
        self.addSubview(view)
        self.view.translatesAutoresizingMaskIntoConstraints = false
        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[view]|", options: NSLayoutFormatOptions.AlignAllCenterY , metrics: nil, views: ["view": self.view]))
        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[view]|", options: NSLayoutFormatOptions.AlignAllCenterX , metrics: nil, views: ["view": self.view]))
    }
Run Code Online (Sandbox Code Playgroud)