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?

2
  • 4
    Write a custom class instead of a computed property. Commented Mar 14, 2018 at 17:05
  • Related: stackoverflow.com/questions/29030426/… Commented Mar 14, 2018 at 17:15

2 Answers 2

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
}

}
Sign up to request clarification or add additional context in comments.

1 Comment

Just a note that exposing the intrinsic state of a class kinda breaks encapsulation, exposing a String property instead would not have this problem.
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")

1 Comment

Your buildHeaderView returns a Void, might want to update the return value.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.