以编程方式将自定义视图添加到另一个视图

时间:2017-03-20 14:26:06

标签: ios swift swift3 uikit

我使用.xib文件为布局创建了一个自定义视图。我想以编程方式创建此视图并将其作为子视图添加到不同的视图中。

子视图类:

class Subview: UIView {

@IBOutlet var view: UIView!
@IBOutlet var titleLabel: UILabel!
@IBOutlet var textLabel: UILabel!

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

    Bundle.main.loadNibNamed("Subview", owner: self, options: nil)
    self.addSubview(view)
    view.frame = self.bounds
  }
}

我不知道如何去做,唯一的构造函数目前需要一个我没有的NSCoder实例。

我试图给它一个额外的初始化器:

init(title: String, text: String) {
    titleLabel.text = title
    textLabel.text = text
    super.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
}

然后叫它:

let v = Subview(title: dataSource[i].whatever, text: dataSource[i].bla)

但是在尝试打开标签出口时它失败了,因为.xib尚未初始化,这是有道理的。

我已经尝试过使用tableview和自定义单元格而不是以编程方式为页面构建UI,它实际上并不起作用,因为这是一个详细信息页面而我只有一个对象作为我的数据源而不是rowForIndexPath tableview委托所期望的数组。我知道我可以编写一些mapper方法将对象转换为它的属性数组,但如果可能的话我宁愿避免使用它。

感谢。

3 个答案:

答案 0 :(得分:2)

1)转到Subview.xib并确保文件所有者为空。

enter image description here

另外,请确保将您的视图的类选为Subview

enter image description here

2)摆脱初始化程序,所以:

class Subview: UIView {

    @IBOutlet var view: UIView!
    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var textLabel: UILabel!

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

        Bundle.main.loadNibNamed("Subview", owner: self, options: nil)
        self.addSubview(view)
        view.frame = self.bounds
    }
}

应该是:

class Subview: UIView {

    @IBOutlet var view: UIView!
    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var textLabel: UILabel!
}

3)初始化你这样看:

let view = UINib(nibName: "Subview", bundle: nil).instantiate(withOwner: nil, options: nil).first as! Subview

你也可以查看这些。

http://supereasyapps.com/blog/2014/12/15/create-an-ibdesignable-uiview-subclass-with-code-from-an-xib-file-in-xcode-6

How to initialise a UIView Class with a xib file in Swift, iOS

祝你好运!

答案 1 :(得分:0)

如果你需要处理IBOutlets,我建议你使用UIViewController作为xib的所有者而不是UIView(当从File菜单创建一个UIViewController时,还可以选择创建一个xib)

然后你可以在父视图中以这种方式实例化它

    var subviewController: SubviewController?

    override func viewDidLoad() {
        super.viewDidLoad()

        subviewController = SubviewController(nibName: nil, bundle: nil)

        self.view.addSubview(subviewController!.view)

        //Remember to call the IBOutlets only after adding the view
        subviewController!.titleLabel.text = "This is the title" 

        subviewController!.view.frame = self.view.frame //Not suggested
        //Instead set constraints here
    }

无论哪种方式,您都必须按Swift: Add a xib into a UIView

中的建议设置约束或使用viewDidLayoutSubviews()结束

答案 2 :(得分:0)

自定义子类可能很棘手,尤其是在使用xib文件时。根据您已经显示的代码,您不清楚哪里出错 - 但是,可能会丢失Outlet连接。

这是一个工作示例 - 包括Obj-C和Swift版本,包括在Interface Builder中使用自定义类。特别针对您尝试做的事情,请查看Swift3 / SW3LoadFromXIB示例:

https://github.com/DonMag/IBDesignInspect