Using AutoLayout with UIView Subclasses in Playgrounds

myview1x

Playgrounds on the Mac and iPad are a great way to develop quick prototypes for new classes. Recently I had the need to create a UIView subclass that contained a few labels. Unfortunately, I couldn’t get my labels to display in the playground. When I used a UIViewController instead of a UIView, everything displayed properly. However, when I changed the parent class to UIView and made the few appropriate changes, my background color changed but my labels no longer appeared. So, instead of seeing this:

view_goal

I was seeing this:

view_problem

My initial thought was to configure the label in layoutSubviews() but the result was still the same.

It turns out that the labels will not autolayout inline within the playground.  You must use the PlaygroundSupport module and the liveView window:

import UIKit
import PlaygroundSupport

class MyView: UIView {

  ...

}

let v = MyView(frame: CGRect(x: 0, y: 0, width: 200, height: 150))
PlaygroundPage.current.liveView = v

Here’s a complete example:

import UIKit
import PlaygroundSupport

class MyView: UIView {
    
    let label = UILabel()
    
    private func setup() {
        self.backgroundColor = UIColor.green

        label.translatesAutoresizingMaskIntoConstraints = false
        label.text = "Hello world"
        label.textAlignment = .center
        self.addSubview(label)
        
        let margins = self.layoutMarginsGuide
        
        label.leadingAnchor.constraint(equalTo: margins.leadingAnchor, constant: 0).isActive = true
        label.trailingAnchor.constraint(equalTo: margins.trailingAnchor, constant: 0).isActive = true
        label.topAnchor.constraint(equalTo: margins.topAnchor, constant: 0).isActive = true
        label.bottomAnchor.constraint(equalTo: margins.bottomAnchor, constant: 0).isActive = true
        
    }
    
//    override func layoutSubviews() {
//    }
    
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()

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

let v = MyView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
PlaygroundPage.current.liveView = v
v