Justin.Shim
Justin.Shim

Reputation: 339

How to control subview of container view in swift?

I'm making my app UI by code.

I usually use a constainer view(just UIView) to make hierarchy.

When I'm using container view, I feel like there is much better way than I using.

Below code is the way I write.

I make all view components as global variable.

And set them on initView()

let conditionContainerView:UIView = {
        let view = UIView()
        return view
    }()

    let conditionSubContainerView:UIView = {
        let view = UIView()
        return view
    }()

    let firstButton:UIButton = {
        let btn = UIButton()
        btn.titleLabel?.font = UIFont.systemFont(ofSize:14, weight: .bold)
        return btn
    }()

    let secondButton:UIButton = {
        let btn = UIButton()
        btn.titleLabel?.font = UIFont.systemFont(ofSize:14, weight: .bold)
        return btn
    }()

    let thirdButton:UIButton = {
        let btn = UIButton()
        btn.titleLabel?.font = UIFont.systemFont(ofSize:14, weight: .bold)
        return btn
    }()

func initView() {
        view.backgroundColor = .white

        view.addSubview(conditionContainerView)
        conditionContainerView.addSubview(conditionSubContainerView)
        conditionSubContainerView.addSubview(firstButton)
        conditionSubContainerView.addSubview(secondButton)
        conditionSubContainerView.addSubview(thirdButton)

        view.addConstraintsWithFormat(format: "H:|[v0]|", views: conditionContainerView)
        view.addConstraintsWithFormat(format: "V:|[v0(35)]", views: conditionContainerView)

        conditionSubContainerView.addConstraintsWithFormat(format: "H:[v0(50)]-8-[v1(50)]-8-[v2(50)]", views: firstButton, secondButton, thirdButton)
        conditionSubContainerView.addConstraintsWithFormat(format: "V:|[v0]|", views: firstButton)
        conditionSubContainerView.addConstraintsWithFormat(format: "V:|[v0]|", views: secondButton)
        conditionSubContainerView.addConstraintsWithFormat(format: "V:|[v0]|", views: thirdButton)

        firstButton.setTitle("first", for: .normal)
        secondButton.setTitle("second", for: .normal)
        thirdButton.setTitle("third", for: .normal)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        initView()
    }

The reason why I use this way is I can't figure out the way I can access subview of container view.

This is what I want to use.

let conditionContainerView:UIView = {
        let view = UIView()
        return view
    }()

    let conditionSubContainerView:UIView = {
        let view = UIView()

        let firstButton = UIButton()
        firstButton.titleLabel?.font = UIFont.systemFont(ofSize:14, weight: .bold)
        let secondButton = UIButton()
        secondButton.titleLabel?.font = UIFont.systemFont(ofSize:14, weight: .bold)
        let thirdButton = UIButton()
        thirdButton.titleLabel?.font = UIFont.systemFont(ofSize:14, weight: .bold)

        view.addSubview(firstButton)
        view.addSubview(secondButton)
        view.addSubview(thirdButton)

        view.addConstraintsWithFormat(format: "H:[v0(50)]-8-[v1(50)]-8-[v2(50)]", views: firstButton, secondButton, thirdButton)
        view.addConstraintsWithFormat(format: "V:|[v0]|", views: firstButton)
        view.addConstraintsWithFormat(format: "V:|[v0]|", views: secondButton)
        view.addConstraintsWithFormat(format: "V:|[v0]|", views: thirdButton)

        return view
    }()

func initView() {
        view.backgroundColor = .white

        view.addSubview(mapView)

        view.addSubview(conditionContainerView)
        conditionContainerView.addSubview(conditionSubContainerView)

        view.addConstraintsWithFormat(format: "H:|[v0]|", views: conditionContainerView)
        view.addConstraintsWithFormat(format: "V:|[v0(35)]", views: conditionContainerView)

        conditionSubContainerView.firstButton.setTitle("first", for: .normal)
        conditionSubContainerView.secondButton.setTitle("second", for: .normal)
        conditionSubContainerView.thirdButton.setTitle("third", for: .normal)

    }

    override func viewDidLoad() {
        super.viewDidLoad()

        initView()
    }

But I can't use the code

conditionSubContainerView.firstButton.setTitle("first", for: .normal)

This maybe SO easy question to someone. Maybe it's nothing. But I really want to know the better way to make the code clean and shorter.

Thank you for your advice.

Upvotes: 0

Views: 1001

Answers (2)

Mike H
Mike H

Reputation: 507

You need to subclass from UIView

final class SomeView: UIView {
    lazy var button: UIButton = {
        return UIButton()
    }()
}

Then in view controller:

class ViewController: UIViewController {
  let containerView = SomeView()

  override func loadView() {
      view = containerView
  }
}

and use containerView instead of self.view

func videDidLoad() {
   super.viewDidLoad()

   containerView.button.setTitle("Test", for: .normal)
}

Upvotes: 1

Lokesh SN
Lokesh SN

Reputation: 1593

Solving this is totally based on your use-case:-

If you are planning to access these buttons from the view a lot, and you have a lot of buttons/elements to share, I'd recommend creating a custom UIView and making these elements accessible to public

Else if this is a one-time process, just assign the titles for the buttons as soon as you instantiate them

Finally, just to answer your question, here's a not-so-efficient way to solve this (especially when you are dealing with a lot of subviews). Three buttons in your case is not that big of a deal. Assign tags to those buttons and filter them if you ultimately feel the need for it:-

let conditionSubContainerView:UIView = {
    let view = UIView()

    let firstButton = UIButton()
    firstButton.tag = 1 // <- assign tags this way
    firstButton.titleLabel?.font = UIFont.systemFont(ofSize:14, weight: .bold)
    let secondButton = UIButton()
    secondButton.tag = 2
    secondButton.titleLabel?.font = UIFont.systemFont(ofSize:14, weight: .bold)
    let thirdButton = UIButton()
    thirdButton.tag = 3
    thirdButton.titleLabel?.font = UIFont.systemFont(ofSize:14, weight: .bold)

    view.addSubview(firstButton)
    view.addSubview(secondButton)
    view.addSubview(thirdButton)

    return view
}()

and filter them using their tags that you assigned:-

if let yourButton = conditionSubContainerView.subviews.filter({$0.tag == 1}).first as? UIButton{
    print("This works and you'll get your firstButton but have this as your last option")
}

Upvotes: 1

Related Questions