【问题标题】:Adding constraints programmatically leads to unexpected behavior以编程方式添加约束会导致意外行为
【发布时间】:2019-04-04 15:14:15
【问题描述】:

我正在玩弄约束,试图了解它们是如何工作的,并尝试学习如何在没有 IB 的情况下构建 UI,但我没有得到预期的结果。在下面的代码中,如果我在最后注释掉约束,我可以看到紫色视图。如果我取消注释它们,我得到的只是一个空窗口,我希望视图被固定在主视图的左侧、右上角。

我也尝试使用 centerX 和 centerY 属性做类似的事情,尝试将视图居中在窗口中间,当它们被激活时,我再次得到一个空窗口。

任何帮助表示赞赏!

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
}  
}

编辑:我还在下面包含了我的 AppDelegate 代码。我对这一切还是很陌生,所以代码是我从各种教程中拼凑起来的东西。

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
}
}

【问题讨论】:

    标签: swift macos nsview


    【解决方案1】:

    view.setFrameSize(NSSize(宽度: 600, 高度: 100))

    不久之后,您将使用 heightAnchor 覆盖高度。 尝试使用锚设置宽度

    【讨论】:

    • 感谢您的回复。你能补充一点细节吗?我刚刚开始掌握约束条件,我想确保我理解正确。具体来说,我正在努力理解如何添加视图并调整它的大小。好像我用 SetFrameSize 设置它,然后用 heightAnchor 修改它几行,然后再次尝试添加约束。这样做的正确方法是什么?我确实在高度下添加了一个 widthAnchor ,但这似乎没有任何作用。再次感谢!
    • 我执行以下操作:我创建一个没有大小的视图:self.myView = UIView(frame: .zero) myview.translatesAutoresizingMaskIntoConstraints = falseself.view.addSubview(myView),然后调用一个添加所有约束的函数: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() 只是调用.isActive = true的一种更简洁的方式
    【解决方案2】:

    使用自动布局,您无需触及视图的 frame 属性。然而,当以编程方式工作时,您必须使用视图本身,但在那之后,所有子视图都可以使用约束来调整大小和定位。为了清楚起见,我去掉了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
    
    }
    

    【讨论】:

    • 感谢您的回复,非常感谢!这里肯定有其他事情发生。我注释掉了我的 createMasterView() 并添加了你的。您包含的每个设置都给了我一个空窗口。我将编辑我的问题以包含 appDelegate 代码,以防其中存在导致问题的东西。再次感谢。
    • 所以整个窗口本身都是空白的?听起来你有一个窗口问题。你读过这个吗? stackoverflow.com/questions/28792722/…
    • 我想我在将项目放在一起时使用了它。澄清一下,我看到紫色视图,但每当我尝试添加约束时,它就会消失。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    • 2015-02-21
    相关资源
    最近更新 更多