Hayden McCabe Hayden McCabe - 11 months ago 92
iOS Question

Programmatically created UIView constraints with anchors not being applied

I created the following code in a Playground, using Xcode 8 and Swift 3. Based on what I've read, it seems like this should show a subview, with a size of 30 x 30 points, in the center of a containing UIView. I've also tried various other types of constraints to no avail. The inner UIView just doesn't display.

This is supposed to be part of a custom UIView subclass, using @IBDesignable and @IBInspectable. If I manually set the frame for subview, they work just fine, but I'd like to have the option of having things automatically resize if need be. I've seen a few other examples on here using the Visual Formatting Language, although I haven't had any luck with them either, and I think I'd prefer using anchors. Any clue as to why this doesn't work?

import UIKit

// Define a simple UIView to put a subview in
let outer = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 480))

// Add a little style to verify that properties are updating
outer.layer.borderWidth = 2.0
outer.layer.borderColor = UIColor.green.cgColor

// Create a subview
let inner = UIView(frame: CGRect.zero)

// I believe this is needed to set constraints manually
inner.translatesAutoresizingMaskIntoConstraints = false

// Add the subview. This displays outer, and it's just a box with a border

// Add a color so I can see it
inner.backgroundColor = UIColor.black

// These constraints should be enough to define the position and size
inner.heightAnchor.constraint(equalToConstant: 30.0).isActive = true
inner.widthAnchor.constraint(equalToConstant: 30.0).isActive = true
inner.centerYAnchor.constraint(equalTo: outer.centerYAnchor).isActive = true
inner.centerXAnchor.constraint(equalTo: outer.centerXAnchor).isActive = true

outer.setNeedsDisplay() // This doesn't seem to do anything, but I tried it
inner.setNeedsDisplay() // Same here

inner.frame // Shows as {x 0 y 0 w 0 h 0}

// Show the UIView, which looks exactly the same as before.

Answer Source

Replace the two setNeedsDisplay() calls with