4
votes

I was making a list in the form of scrollview in swift where the view consists of various types such as labels, button etc.

However when i added the button to the subview, they were not displayed although all other labels etc were displayed. I also tried messing around in the constraints and anchors. On the other hand when i added the same button to self.view.addsubview instead of scrollview.addsubview, they were displayed just not scrolling since not a part of the scrollview anymore. I even removed the label to make sure that the buttons were not being overlapped(didn't work either)

I also tried to see the code in "code debug hierarchy " (3D mode), i couldn't see the button there either even though i had added it

Below is my code with an example of label, scrollview and button. It be great if anyone could provide any insights.....thanks either way....

................scrollview..........................

var editInfoView : UIScrollView = {

    let view = UIScrollView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.contentSize.height = 700
    view.backgroundColor = tableBackGroundColor
    view.frame = CGRect(x: 0, y: 220, width: 375, height: 400)

    return view
}()

.......................label...................

vehicleNumberLabel.translatesAutoresizingMaskIntoConstraints = false
    vehicleNumberLabel.textColor = .white
    vehicleNumberLabel.text = "Vehicle Number"
    vehicleNumberLabel.textAlignment = .left

    editInfoView.addSubview(vehicleNumberLabel)

    vehicleNumberLabel.leftAnchor.constraint(equalTo: editInfoView.leftAnchor).isActive = true
    vehicleNumberLabel.topAnchor.constraint(equalTo: editInfoView.topAnchor, constant: 100).isActive = true
    vehicleNumberLabel.widthAnchor.constraint(equalToConstant: 160).isActive = true
    vehicleNumberLabel.heightAnchor.constraint(equalToConstant: 20).isActive = true

.....................button................................

vehicleNumberButton.translatesAutoresizingMaskIntoConstraints = false
    vehicleNumberButton.setTitleColor(tableTextColor, for: .normal)
    vehicleNumberButton.setTitle("Vehicle Number", for: .normal)
    vehicleNumberButton.tintColor = tableTextColor
    vehicleNumberButton.backgroundColor = tableTextColor

    editInfoView.addSubview(vehicleNumberButton)

    vehicleNumberButton.rightAnchor.constraint(equalTo: editInfoView.rightAnchor).isActive = true
    vehicleNumberButton.topAnchor.constraint(equalTo: editInfoView.topAnchor, constant: 400).isActive = true
    vehicleNumberButton.widthAnchor.constraint(equalToConstant: 600).isActive = true
    vehicleNumberButton.heightAnchor.constraint(equalToConstant: 255).isActive = true
1
Why you add the constrains after you add it to the view? Maybe you should first add it to the view, after you setted the constrainsJonathan
Jonathan, i add constraints after adding it to the view because if i add to the view before, it gives me this error (Thread 1: signal SIGABRT). And this way works just fine for label but not for the button?vgvishesh23113
Ah okay, in wich function do you add the buttons and labels? In viewDidLoad?Jonathan
i declare them in VC, define in viewdidload and add to the view in a seperate method just for constraints and setup, same for labels and buttonvgvishesh23113
Take a look at this, i thik you should add your Elements in the init function: medium.com/written-code/…Jonathan

1 Answers

1
votes

Although I cannot determine the root cause of your issue with the code and explanation provided I suspect the frame of your UIScrollView() is zero after viewDidAppear(_:) adding subviews to a CGRect.zero can cause some strange behavior with the layout engine. When we create constraints programmatically we are creating a combination of inequalities, equalities, and priorities to restrict the view to a particular frame. If a the value of these constraint equations is incorrect it changes how your relating views appear. Its good practice to avoid the use of leftAnchor and rightAnchor as well, because views may flip direction based on language (writing direction) and user settings.

ViewController.swift

import UIKit

class ViewController: UIViewController {

    var editInfoScrollView : UIScrollView = {
        let view = UIScrollView()
        view.translatesAutoresizingMaskIntoConstraints = false
        view.isUserInteractionEnabled = true
        view.alwaysBounceVertical = true
        view.isScrollEnabled = true
        view.contentSize.height = 700
        view.backgroundColor = UIColor.red.withAlphaComponent(0.3)
        // Does nothing because `translatesAutoresizingMaskIntoConstraints = false`
        // Instead, set the content size after activating constraints in viewDidAppear
        //view.frame = CGRect(x: 0, y: 220, width: 375, height: 400)
        return view
    }()

    var vehicleNumberLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.textColor = UIColor.black
        label.text = "Vehicle Number"
        label.textAlignment = .left
        return label
    }()

    lazy var vehicleNumberButton: UIButton = {
        let button = UIButton()
        button.translatesAutoresizingMaskIntoConstraints = false
        button.tag = 1
        button.setTitleColor(UIColor.black, for: .normal)
        button.setTitle("Go to Vehicle", for: .normal)
        button.tintColor = UIColor.white
        button.backgroundColor = UIColor.clear
        button.layer.cornerRadius = 30 // about half of button.frame.height
        button.layer.borderColor = UIColor.black.cgColor
        button.layer.borderWidth = 2.0
        button.layer.masksToBounds = true
        button.addTarget(self, action: #selector(handelButtons(_:)), for: .touchUpInside)
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.white

        self.setupSubviews()

    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        self.editInfoScrollView.contentSize = CGSize(width: self.view.frame.width, height: 700.0)
    }

    func setupSubviews() {
        self.view.addSubview(editInfoScrollView)
            editInfoScrollView.addSubview(vehicleNumberLabel)
            editInfoScrollView.addSubview(vehicleNumberButton)

        let spacing: CGFloat = 12.0

        let constraints:[NSLayoutConstraint] = [

            editInfoScrollView.widthAnchor.constraint(equalTo: self.view.widthAnchor),
            editInfoScrollView.heightAnchor.constraint(equalToConstant: 400.0),
            editInfoScrollView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
            editInfoScrollView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor, constant: 220.0),

            vehicleNumberLabel.leadingAnchor.constraint(equalTo: editInfoScrollView.leadingAnchor, constant: spacing),
            vehicleNumberLabel.trailingAnchor.constraint(equalTo: editInfoScrollView.trailingAnchor, constant: -spacing),
            vehicleNumberLabel.centerXAnchor.constraint(equalTo: editInfoScrollView.centerXAnchor, constant: -50),
            vehicleNumberLabel.heightAnchor.constraint(equalToConstant: 75.0),

            vehicleNumberButton.widthAnchor.constraint(equalTo: editInfoScrollView.widthAnchor, multiplier: 0.66),
            vehicleNumberButton.heightAnchor.constraint(equalToConstant: 65.0),
            vehicleNumberButton.topAnchor.constraint(equalTo: vehicleNumberLabel.bottomAnchor, constant: spacing),
            vehicleNumberButton.centerXAnchor.constraint(equalTo: editInfoScrollView.centerXAnchor),

        ]

        NSLayoutConstraint.activate(constraints)
    }



    @objc func handelButtons(_ sender: UIButton) {

        switch sender.tag {
        case 0:
            print("Default button tag")
        case 1:
            print("vehicleNumberButton was tapped")
        default:
            print("Nothing here yet")
        }

    }


}