我有一个经典的垂直 NSSplitViewController 并且在窗格约束中没有成功。
如果右窗格中没有任何内容,我可以毫无问题地调整窗口大小,左窗格的宽度不会改变。
但是,如果我在右窗格中有一个视图,并且我想调整窗口大小以使右窗格的宽度更大,则调整大小的是左窗格:
我知道这是一个约束问题,但我不知道如何解决这些约束。
在拆分视图控制器中,我有以下代码:
class splitViewController: NSSplitViewController {
private var verticalConstraints: [NSLayoutConstraint] = []
private var horizontalConstraints: [NSLayoutConstraint] = []
private var treeControllerObserver: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(handleSelectionChange(_:)),
name: Notification.Name(OutlineViewController.NotificationNames.selectionChanged),
object: nil)
splitView.autosaveName = "SplitViewAutoSave"
}
// MARK: - Detail View Controller Management
private var detailViewController: NSViewController {
let rightSplitViewItem = splitViewItems[1]
return rightSplitViewItem.viewController
}
private var hasChildViewController: Bool {
return !detailViewController.children.isEmpty
}
private func embedChildViewController(_ childViewController: NSViewController) {
// This embeds a new child view controller.
let currentDetailVC = detailViewController
currentDetailVC.addChild(childViewController)
currentDetailVC.view.addSubview(childViewController.view)
// Build the horizontal, vertical constraints so that an added child view controller matches the width and height of its parent.
let views = ["targetView": childViewController.view]
horizontalConstraints =
NSLayoutConstraint.constraints(withVisualFormat: "H:|[targetView]|",
options: [],
metrics: nil,
views: views)
NSLayoutConstraint.activate(horizontalConstraints)
verticalConstraints =
NSLayoutConstraint.constraints(withVisualFormat: "V:|[targetView]|",
options: [],
metrics: nil,
views: views)
NSLayoutConstraint.activate(verticalConstraints)
}
//MARK: - Notifications
// Listens for selection changes to the NSTreeController.
@objc
private func handleSelectionChange(_ notification: Notification) {
// Examine the current selection and adjust the UI.
// Make sure the notification's object is a tree controller.
guard let outlineView = notification.object as? NSOutlineView else { return }
let leftSplitViewItem = splitViewItems[0]
if let outlineViewControllerToObserve = leftSplitViewItem.viewController as? OutlineViewController {
let currentDetailVC = detailViewController
// Let the outline view controller handle the selection (helps you decide which detail view to use).
if let vcForDetail = outlineViewControllerToObserve.viewControllerForSelection(outlineView.selectedRowIndexes) {
if hasChildViewController && currentDetailVC.children[0] != vcForDetail {
/** The incoming child view controller is different from the one you currently have,
so remove the old one and add the new one.
*/
currentDetailVC.removeChild(at: 0)
// Remove the old child detail view.
detailViewController.view.subviews[0].removeFromSuperview()
// Add the new child detail view.
embedChildViewController(vcForDetail)
} else {
if !hasChildViewController {
// You don't have a child view controller, so embed the new one.
embedChildViewController(vcForDetail)
}
}
} else {
// No selection. You don't have a child view controller to embed, so remove the current child view controller.
if hasChildViewController {
currentDetailVC.removeChild(at: 0)
detailViewController.view.subviews[0].removeFromSuperview()
}
}
}
}
}
(我在旧的 stackoverflow 答案中找到了代码,我已经复制了它,但我不习惯编写约束,因为它是在 embedViewController 方法中编写的。
我确切地说,在 IB 中,我将窗格的持有优先级约束固定如下:左窗格为 200,右窗格为 199
有人能帮我吗?