I have a blank Swift project in Xcode and am not using storyboard. I have a view that I've added in code under viewDidLoad:
var view1 = UIView()
view1.backgroundColor = .red
view.addSubview(view1)
view1.translatesAutoresizingMaskIntoConstraints = false
I then add constraints:
NSLayoutConstraint.activate([
view1.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
view1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20),
view1.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
view1.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20)
])
The view loads and looks fine in the simulator. But I've been having some issues with some other views in another project so I have built the above for testing. So what I've discovered is that even though the above builds and works, if I check for ambiguous layouts using:
print(view1.hasAmbiguousLayout)
I get errors logged:
2021-02-14 15:26:34.919048+1100 autolayoutextensions[6603:4438601] [LayoutConstraints] View has an ambiguous layout. See "Auto Layout Guide: Ambiguous Layouts" for help debugging. Displaying synopsis from invoking -[UIView _autolayoutTrace] to provide additional detail.UIView:0x13360c3b0- AMBIGUOUS LAYOUT for UIView:0x13360c3b0.Width{id: 9}, UIView:0x13360c3b0.Height{id: 12}
Legend: * - is laid out with auto layout + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES • - layout engine host true
The only way I can get these errors to NOT get logged, is by also setting the ViewController's main view as follows:
view.translatesAutoresizingMaskIntoConstraints = false
By doing this, I know get the following log output:
false
So my question is this... I haven't read anywhere in Apple's documentation (or here, Googling etc) that says you have to set the viewController's view.translatesAutoresizingMaskIntoConstraints to false. The documentation only talks about views that are added . Have I missed something? Apologies if this is just my understanding but would be good to get this clarified.
Post
Replies
Boosts
Views
Activity
I have a child view controller as follows:
class ChildViewControllerAAA: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
let newView = UIView()
view.addSubview(newView)
newView.backgroundColor = .systemBlue
newView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
newView.topAnchor.constraint(equalTo: view.topAnchor),
newView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
newView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
newView.heightAnchor.constraint(equalToConstant: 123),
])
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
calculatePreferredSize()
}
func calculatePreferredSize() {
let targetSize = CGSize(width: view.bounds.width,
height: UIView.layoutFittingCompressedSize.height)
preferredContentSize = view.systemLayoutSizeFitting(targetSize)
}
}
The above works fine and if I instantiate the above view controller full screen, it works fine.
But if I then try to embed the above in another view controller and use it as a child view controller, the embedded blue UIView newView does not work correctly and I get broken constraints with the height of newView being broken by the Auto Layout engine. This is the code where I add it as a child VC:
class ViewController: UIViewController {
var container : UIView!
var childVC : ChildViewController!
var containerHeightConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .purple
container = UIView()
container.backgroundColor = .systemPink
container.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(container)
container.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
container.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
container.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
containerHeightConstraint = NSLayoutConstraint()
containerHeightConstraint = container.heightAnchor.constraint(equalToConstant: 0)
containerHeightConstraint.isActive = true
childVC = ChildViewController()
addChild(childVC)
container.addSubview(childVC.view)
childVC.view.frame = container.bounds
childVC.didMove(toParent: self)
childVC.view.translatesAutoresizingMaskIntoConstraints = false
}
override func preferredContentSizeDidChange(forChildContentContainer container: UIContentContainer) {
super.preferredContentSizeDidChange(forChildContentContainer: container)
if (container as? ChildViewControllerAAA) != nil {
containerHeightConstraint.constant = container.preferredContentSize.height
}
}
}
What I'm trying to work out, using the systemLayoutSizeFitting with UIView.layoutFittingCompressedSize is get back the minimum required size of the child view and then constrain it to bottom of the parent view controller. So in this mockup, it should only be 123 high.
I'm starting with a blank iOS App project with the following code:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
testMethodB()
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
print("called: traitCollectionDidChange")
testMethodA()
}
func testMethodA() {
}
func testMethodB() {
}
}
I have breakpoints on line 17 traitCollecitonDidChange, line 21 (print), line 31 and line 36.
The breakpoint on line 36 gets called but the breakpoints on 17, 21, 23 and 31 aren't getting called even though the print line on 21 prints. I can't work out why these breakpoints aren't working. I'm running in debug mode, have cleared DerivedData, reinstalled Xcode amongst other things...