在视图控制器中访问 UIView 子类

accessing UIView subclass in view controller

假设我有 SomeViewController: UIViewController,并且我有一个自定义视图 CustomView: UIView,定义为 XIB,我想显示它。这个自定义视图将在其他视图控制器中重复使用,甚至在同一个视图控制器中多次使用。

class CustomView: UIView {
  @IBOutlet public var label: UILabel!
}

我添加此视图的方式一直是:

class UIExamples: UIViewController {
  @IBOutlet private var myView: UIView!

  override func viewDidLoad() {
    super.viewDidLoad()
    // Assume makeViewFromNib returns the view [0] in the Nib. 
    let customView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
    customView.frame = myView.bounds
    myView.addSubview(customView)
  }
}

假设稍后我想通过 public 属性 label 修改一些关于 CustomView 的内容。

我可以在 viewDidLoad 中完成它只是因为我可以访问 customView,但是如果我想在其他功能中更改它怎么办?我所看到的是必须做

let customView = myView.subviews[0] as! CustomView
customView.label.text = "some text"

这看起来不对。

所以,我认为正确的方法应该是这样的:

class UIExamples: UIViewController {
  @IBOutlet public var customView: CustomView! // Now this is always a CustomView type

  override func viewDidLoad() {
    super.viewDidLoad()

    // Assume makeViewFromNib returns the view [0] in the Nib. 
    customView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
    customView.label.text = "some text" // DOES NOT WORK!
  }
}

最后一行 customView.label.text 不起作用。事实上,屏幕上什至看不到标签。我究竟做错了什么?

好的,没读过(或者可能在编辑之前读过)你使用 xib。如果 ViewController 是从带有标签的 xib 创建的,这将是正确的方法:

在 xib 中设置 myView class:

然后连接IBOutlet(从这里的xib中删除当前的一个:

然后从代码)。

现在 myView.label.text = "some text" 应该可以正常工作了。 祝你好运!


如果您通过代码创建视图,请按以下方式进行:

class UIExamples: UIViewController {
  @IBOutlet private var myView: CustomView!

  override func viewDidLoad() {
    super.viewDidLoad()
    // Assume makeViewFromNib returns the view [0] in the Nib. 
    myView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
    myView.frame = view.bounds
    view.addSubview(myView)
  }
}

因为您已经 属性 将此视图存储在您的视图控制器中,所以没有必要在子视图中挖掘,它会像那样工作

myView.label.text = "some text"

以及

的原因
customView = makeViewFromNib(nib: "\(CustomView.self)", owner: self) as! CustomView
    customView.label.text = "some text"

不工作是因为它是全新的视图,没有添加到您的视图控制器子视图中(顺便说一句,框架也没有设置)。并且因为您更改了 customView 属性 的值,它现在不指向子视图中存在的旧视图实例(您仍然可以看到 "old one" 但不能更改它)。

但我真的建议使用创建一次的指针,因为正确 class 可以避免强制转换。 (或者直接在xib/storyboard中创建视图,否则@IBOutlet不需要)

发布我自己的答案。

  1. 创建 XIB 文件。
  2. 创建 UIView 子class Swift 文件。
  3. 在 XIB 文件所有者的 Identify Inspector 自定义 class 字段下,输入 UIView subclass 名称(您的自定义视图)。
  4. 在 XIB 文件所有者的连接检查器下,确保 Swift 文件中的所有 IBOutlets 都已连接。
  5. 向视图控制器添加一个视图,并在其 Identify Inspector 自定义 class 类型下,指定自定义 class 名称。

重要: * 在您的 XIB swift 文件中,您必须正确加载 XIB 内容视图。

...

  /// Initializer used by Interface Builder.
  required init?(coder: NSCoder) {
    super.init(coder: coder)
    configure()
  }

  /// Initializer used programmatically.
  override init(frame: CGRect) {
    super.init(frame: frame)
    configure()
  }

...

func configure() {
  let contentView = // here use many of the functions available on the internet to 
                    // load a view from a nib. 
  // Then add this view to the view hierarchy. 
    addSubview(contentView)
}