0

I'm playing around with constraints, trying to learn how they work and to try and learn how to build a UI without IB, and I'm not getting the results I anticipated. In the code below, if I comment out the constraints at the end, I can see the purple view. If I uncomment them, all I get is an empty window where I would expect the view to be pinned to the left, topped right edges of the main view.

I've also tried doing a similar thing with the centerX and centerY properties to try and center the view in the middle of the window, again I get an empty window when those are activated.

Any help appreciated!

import Cocoa

class ViewController : NSViewController {

override func loadView() {

    // NSMakeRect parameters do nothing?
    let view = NSView(frame: NSMakeRect(0,0,400,2000))
    view.wantsLayer = true
    view.layer?.borderWidth = 5
    view.layer?.borderColor = NSColor.gray.cgColor
    self.view = view
}

override func viewWillAppear() {

    super.viewWillAppear()

    // Do any additional setup after loading the view.
    createMasterView()
}



func makeView() -> NSView {
    let view = NSView()
    view.translatesAutoresizingMaskIntoConstraints = false
    view.setFrameSize(NSSize(width: 600, height: 100))
    view.wantsLayer = true
    view.heightAnchor.constraint(equalToConstant: 1000)
    return view
}

func createMasterView() {

    let mainView = self.view
    let headerView = makeView()

    headerView.layer?.backgroundColor = NSColor.purple.cgColor
    headerView.layer?.borderWidth = 5
    headerView.layer?.borderColor = CGColor.black

    mainView.translatesAutoresizingMaskIntoConstraints = false
    mainView.addSubview(headerView)

    headerView.topAnchor.constraint(equalTo: mainView.topAnchor).isActive = true
    headerView.leadingAnchor.constraint(equalTo: mainView.leadingAnchor).isActive = true
    headerView.trailingAnchor.constraint(equalTo: mainView.trailingAnchor).isActive = true
}  
}

Edit: I'm also including my AppDelegate code below. I'm still very new to all this so the code is stuff I've cobbled together from various tutorials.

import Cocoa

class AppDelegate: NSObject, NSApplicationDelegate {

var windowController: NSWindowController!
var window: NSWindow!
var windowTitle = "Test App"
var customBGColor = NSColor(red: 1, green: 1, blue: 1, alpha: 1)

func applicationDidFinishLaunching(_ aNotification: Notification) {

    createMainWindow()
}  

func createMainWindow() {
    window = NSWindow()
    // window.alphaValue = 0.5
    window.backgroundColor = customBGColor
    window.title = windowTitle
    window.styleMask = NSWindow.StyleMask(rawValue: 0xf)
    window.backingType = .buffered
    window.contentViewController = ViewController()
    window.setFrame(NSRect(x: 700, y: 200, width: 1920, height: 1080), display: false)
    windowController = NSWindowController()
    windowController.contentViewController = window.contentViewController
    windowController.window = window
    windowController.showWindow(self)
}

func applicationWillTerminate(_ aNotification: Notification) {
    // Insert code here to tear down your application
}
}

2 Answers 2

0

view.setFrameSize(NSSize(width: 600, height: 100))

You are overriding the height shortly afterwards with the heightAnchor. Try setting width as well with an anchor

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the reply. Could you add a little more detail? I'm just starting to get to grips with constraints and I want to make sure I understand correctly. Specifically, I'm struggling with understanding how to add a view and resize it. It seems like I'm setting it with the SetFrameSize, then modifying it with the heightAnchor a couple of lines down, then again by trying to add constraints. What's the correct way to do this? I did add a widthAnchor under the height one but that doesn't seem to do anything. Thanks again!
I do the following: I create a view without a size: self.myView = UIView(frame: .zero) myview.translatesAutoresizingMaskIntoConstraints = false self.view.addSubview(myView) and then calling a function that adds all the constraints: func addConstraints() { NSLayoutConstraint.activate([ myView.topAnchor.constraint(equalTo: self.topAnchor), myView.bottomAnchor.constraint(equalTo: self.bottomAnchor), myView.leftAnchor.constraint(equalTo: self.leftAnchor), myView.rightAnchor.constraint(equalTo: self.rightAnchor) ]) }
NSLayoutConstraint.activate() is just a cleaner way of calling .isActive = true
0

With auto layout, you don't touch the frame property of the view. When working programmatically, however, you have to with the view itself, but after that, all subviews can be sized and positioned using constraints. For clarity, I got rid of makeView():

func createMasterView() {

    let headerView = NSView() // instantiate
    headerView.layer?.backgroundColor = NSColor.purple.cgColor // style
    headerView.layer?.borderWidth = 5
    headerView.layer?.borderColor = CGColor.black
    headerView.translatesAutoresizingMaskIntoConstraints = false // disable mask translating
    view.addSubview(headerView) // add as a subview

    // then configure constraints

    // one possible setup
    headerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    headerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    headerView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    headerView.heightAnchor.constraint(equalToConstant: 100).isActive = true

    // another possible setup
    headerView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    headerView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    headerView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    headerView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5).isActive = true

    // another possible setup
    headerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    headerView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    headerView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -50).isActive = true
    headerView.heightAnchor.constraint(equalTo: view.heightAnchor, constant: -50).isActive = true

}

3 Comments

Thanks for the reply, I really appreciate it! There's definitely something else going on here. I commented out my createMasterView() and added yours. Each of the setups you included gives me an empty window. I'll edit my question to include the appDelegate code in case there's something in there that's causing problems. Thanks again.
So the entire window itself is blank? Sounds like you have a window problem. Have you read this? stackoverflow.com/questions/28792722/…
I think I used that when putting the project together. To clarify, I see the purple view but whenever I try to add a constraint it disappears.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.