Wayne Rumble Wayne Rumble - 15 days ago 14
Swift Question

Stackview label not adding programatically

Im trying to do everything without a story board but keep getting nil when adding my label but i cant see why. Im sure its dead simple and im being blind but i just cant see it after a lot of googling.

View Controller:

class SquaresViewController: UIViewController {

let stackView = OAStackView()
let titleView = TitleView(frame: CGRect.zero)

@IBOutlet var squaresCollectionView: UICollectionView!

override func viewDidLoad() {
super.viewDidLoad()

stackView.axis = .vertical
stackView.translatesAutoresizingMaskIntoConstraints = false

stackView.addArrangedSubview(titleView)
titleView.snp.makeConstraints { make in
make.height.equalTo(50)
make.top.equalTo(view.snp.top)
make.left.equalTo(view.snp.left)
make.right.equalTo(view.snp.right)
}

}
}


titleView:

import UIKit

class TitleView: UIView {

@IBOutlet weak var titleText: UILabel!

override init(frame: CGRect) {
super.init(frame: frame)
self.translatesAutoresizingMaskIntoConstraints = false
createView()
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

func createView() {
titleText = UILabel(frame: CGRect.zero)
titleText.translatesAutoresizingMaskIntoConstraints = false

titleText.text = "Tappy tap tap a square!"
titleText.textAlignment = .center
titleText.numberOfLines = 0

self.addSubview(titleText)

titleText.snp.makeConstraints { make in
make.edges.equalTo( self.snp.edges )
}


}
}


When building it fails at:

titleText.translatesAutoresizingMaskIntoConstraints = false


with:

fatal error: unexpectedly found nil while unwrapping an Optional value


Any help would be great, im sure its simple but i cant see for looking anymore. Thanks

Wes Wes
Answer

First of all, I don't understand why you created an IBOutlet for titleText if you don't want to use storyboards. If you don't want to use storyboards, change the implementation to:

var titleText : UILabel!

Secondly, the application is crashing because you are asking it to perform an operation on a view that is not yet added to the hierarchy. For ease of reading I have commented out all lines except those that are important. See below:

func createView() {
    //titleText = UILabel(frame: CGRect.zero)
    titleText.translatesAutoresizingMaskIntoConstraints = false // <-- You are trying to perform an operation on titleText here

    //titleText.text = "Tappy tap tap a square!"
    //titleText.textAlignment = .center
    //titleText.numberOfLines = 0

    self.addSubview(titleText) // <-- but you are adding it to the view hierarchy here

    //titleText.snp.makeConstraints { make in
        //make.edges.equalTo( self.snp.edges )
    //}
}

titleText has to be added to the view hierarchy before you can call translatesAutoresizingMaskIntoConstraints on it, like so:

self.view.addSubview(titleText)
titleText.translatesAutoresizingMaskIntoConstraints = false // <-- Here we are waiting until the view has been added to the hierarchy to perform operations on it

So try changing implementation to look like so:

import UIKit

class TitleView: UIView {

    var titleText: UILabel!

    override init(frame: CGRect) {
        // leave as is, removed for space
    }

    required init?(coder aDecoder: NSCoder) {
        // leave as is, removed for space
    }

    func createView() {
        titleText = UILabel(frame: CGRect.zero)
        titleText.text = "Tappy tap tap a square!"
        titleText.textAlignment = .center
        titleText.numberOfLines = 0

        self.addSubview(titleText)
        titleText.translatesAutoresizingMaskIntoConstraints = false

        titleText.snp.makeConstraints { make in
            make.edges.equalTo( self.snp.edges )
        }
    }
}