1

Let's say I am describing my own UIView, let's call it a HeaderView. I want the HeaderView to have the exact same properties, but only differ in label text. Here is how I currently have it:

private let headerView: UIView = {
    let screenSize = UIScreen.main.bounds
    let screenWidth = screenSize.width
    let screenHeight = screenSize.height

    let view = UIView()
    view.backgroundColor = .white
    view.heightAnchor.constraint(equalToConstant: 65).isActive = true

    let label = UILabel()
    label.font = UIFont.systemFont(ofSize: 30)
    label.textAlignment = .left
    label.textColor = .black
    label.text = "Search"

    view.addSubview(label)
    label.translatesAutoresizingMaskIntoConstraints = false
    label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8).isActive = true
    label.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 5).isActive = true

    return view
}()

How I'd use it:

 view.addSubview(headerView)
 headerView.translatesAutoresizingMaskIntoConstraints = false
 headerView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
 headerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
 headerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true

What if I want 3 of these header views with varying text? How would I make it into a reusable programmatic view?

Cœur
  • 37,241
  • 25
  • 195
  • 267
user298519
  • 1,052
  • 1
  • 11
  • 27

2 Answers2

2

You can create a subclass of UIView and reuse it anywhere

class HeaderView: UIView {

  let innerview = UIView()
  let innerlabel = UILabel() 

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

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

private func sharedLayout() {

    self.addSubview(innerview)
    self.innerView.backgroundColor = UIColor.red
    innerview.translatesAutoresizingMaskIntoConstraints = false
    innerview.trailingAnchor.constraint(equalTo:self.trailingAnchor).isActive = true
    innerview.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
    innerview.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    innerview.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true

    // configure other items here
}

}
Shehata Gamal
  • 98,760
  • 8
  • 65
  • 87
  • 1
    Just a note that exposing the intrinsic state of a class kinda breaks encapsulation, exposing a `String` property instead would not have this problem. – Cristik Mar 14 '18 at 18:54
0

Instead of a variable you could have a function:

func buildHeaderView(withText text: String) -> UIView {
    let screenSize = UIScreen.main.bounds
    let screenWidth = screenSize.width
    let screenHeight = screenSize.height

    let view = UIView()
    view.backgroundColor = .white
    view.heightAnchor.constraint(equalToConstant: 65).isActive = true

    let label = UILabel()
    label.font = UIFont.systemFont(ofSize: 30)
    label.textAlignment = .left
    label.textColor = .black
    label.text = text

    view.addSubview(label)
    label.translatesAutoresizingMaskIntoConstraints = false
    label.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 8).isActive = true
    label.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 5).isActive = true

    return view
}

Now you could use this function like:

let searchHeaderView = buildHeaderView(withText: "Search")
view.addSubview(searchHeaderView)

let otherView = buildHeaderView(withText: "Other")
user298519
  • 1,052
  • 1
  • 11
  • 27
Reynaldo Aguilar
  • 1,906
  • 1
  • 15
  • 29