【问题标题】:Programatically adding custom view to another view以编程方式将自定义视图添加到另一个视图
【发布时间】:2017-08-11 21:10:19
【问题描述】:

我使用 .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 表视图委托期望的数组。我知道我可以编写一些映射器方法来将对象转换为它的属性数组,但如果可能的话,我宁愿避免这样做。

谢谢。

【问题讨论】:

  • 因为在您的情况下,只有类已被初始化,而不是网点,因为未分配 nib 初始化,您可以尝试self = Bundle.main.loadNibNamed("Subview", owner: self, options: nil)?[0]
  • stackoverflow.com/questions/35659714/… 这应该会有所帮助
  • 感谢您的回复,当我尝试任一解决方案时,我在尝试使用 Bundle.main.loadLibNamed 时看到此错误:此类与键的键值编码不兼容,我认为是网点的问题。我还应该注意,我可以毫无问题地将 xib 添加到我的故事板中,我可能需要创建多个,这就是为什么我需要弄清楚如何以编程方式完成它。

标签: ios swift swift3 uikit


【解决方案1】:

如果您需要处理 IBOutlets,我建议您使用 UIViewController 作为 xib 的所有者,而不是 UIView(从文件菜单创建 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】:

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

    这是一个工作示例 - 包括 Obj-C 和 Swift 版本,包括使用 Interface Builder 中的自定义类。具体到您想要做什么,请查看 Swift3/SW3LoadFromXIB 示例:

    https://github.com/DonMag/IBDesignInspect

    【讨论】:

      【解决方案3】:

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

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

      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 但我发现的唯一问题是边界没有以这种方式设置,并且自定义视图无法正确显示。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多