'create UILabel via function

First of all, I would like to say that I am aware that my approach may be a bit naive, but I have not been programming in Swift for so long and you may forgive my ignorance at this point.

I am currently trying to create UILabels programmatically and in the process I came up with the idea - because the basic properties of the labels basically don't change - to write a function that does this work for me. Apart from the fact that it saves a lot of code.

In the end I want to create labels with different names, whose properties (constraints) I can edit externally with my own functions.

My function, as you see it here, "produces" labels but nothing comes out that Xcode can do anything with.

func createValueLabel(placeHolderValue text: String, labelName name: String) -> UILabel {
    let label = UILabel()

    label.layer.name = name
    label.font = UIFont.boldSystemFont(ofSize: 14)
    label.text = text
    label.textColor = UIColor.init(red: 188 / 255, green: 143 / 255, blue: 143 / 255, alpha: 1.0)
    resourceView.addSubview(label)
    //label.translatesAutoresizingMaskIntoConstraints = false

    return label
}

enter image description here

I would like to put the labels, once they are produced, into a subView.

Is my project basically doomed to fail or am I just being too stupid?

Thanks in advance.



Solution 1:[1]

UILabel is a reference type(Class) As you are returning the label in your method you can assign it to a new variable like:

var myNewLabel = createValueLabel(...)

and later you can change it's property whenever you want like

myNewLabel.text = "newLabelText"

Solution 2:[2]

Firstly refactor your creating label to only create label without adding it to view

func createValueLabel(placeHolderValue text: String, labelName name: String) -> UILabel {
    let label = UILabel()
    label.layer.name = name
    label.font = UIFont.boldSystemFont(ofSize: 14)
    label.text = text
    label.textColor = UIColor.init(red: 188 / 255, green: 143 / 255, blue: 143 / 255, alpha: 1.0)
    return label
}

Then add your label into your view, for example in UIViewController method viewDidLoad and add proper constraints:

override func viewDidLoad() {
    super.viewDidLoad()
    let label = createValueLabel(placeHolderValue: "", labelName: "")
    //adding label to view
    self.view.addSubview(label)
    //adding constraints to labels
    label.translatesAutoresizingMaskIntoConstraints = false
    label.leadingAnchor.constraint(equalTo: self.view.leadingAnchor,constant: 10).isActive = true
    label.trailingAnchor.constraint(equalTo: self.view.trailingAnchor,constant: 10).isActive = true
    label.topAnchor.constraint(equalTo: self.view.topAnchor,constant: 10).isActive = true
    label.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 10).isActive = true
}

Solution 3:[3]

If you're creating the label inside a UIViewController class programmatically, following way is considered a good practice:

let myNewLabel: UILabel = {
    let lbl = UILabel()
    lbl.frame = CGRect(x: 0, y: 0, width: 100, height: 100) //setting frame here or you can change later as well
    lbl.backgroundColor = .white
    lbl.font = UIFont.boldSystemFont(ofSize: 14)
    lbl.textColor = UIColor.init(red: 188 / 255, green: 143 / 255, blue: 143 / 255, alpha: 1.0)
    lbl.translatesAutoresizingMaskIntoConstraints = false //make sure this property is false when programmatically setting constraints
    return lbl
}()

You can later access this property via myNewLabel in viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
    setupMyNewLabel(placeHolderValue: "placeholderValue", labelName: "name")
}

It's good to refactor code based on what purpose each line serve.

fileprivate func setupMyNewLabel(placeHolderValue text: String, labelName name: String) {
    myNewLabel.layer.name = name
    myNewLabel.text = text
    resourceView.addSubview(myNewLabel)

    //setup your constraints here
    myNewLabel.leadingAnchor.constraint(equalTo: self.view.leadingAnchor,constant: 10).isActive = true
    myNewLabel.trailingAnchor.constraint(equalTo: self.view.trailingAnchor,constant: 10).isActive = true
    myNewLabel.topAnchor.constraint(equalTo: self.view.topAnchor,constant: 10).isActive = true
    myNewLabel.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 10).isActive = true
}

Solution 4:[4]

Ok, I have found the error. I tried to change the constrains of the labels via a function and this function did not "know" the created labels, because I executed the function to create the labels in the viewDidLoad. So the created value or label were not global and therefore not recognized.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ghulam Mustafa
Solution 2 Mr.SwiftOak
Solution 3
Solution 4 python_ftw