MacOS Swift Bundle项目:同一Nib文件下拉框切换视图实现方法
Hey there! Since you're new to Swift and macOS development (and working without Storyboards), let's walk through exactly how to switch views dynamically when an NSPopUpButton changes its selection. This approach uses child view controllers to keep your code clean and follows macOS best practices.
1. Prepare View Controllers for Each Item
First, create separate NSViewController subclasses for each view you want to display. For example:
Item1ViewController.swift(with its own Nib file, e.g.,Item1ViewController.nib)Item2ViewController.swift(with its corresponding Nib)
Set up constraints in each Nib so the view fits neatly into a container—this will make swapping seamless later.
2. Configure Your Main Nib
In your main Nib file (e.g., MainView.nib):
- Add an
NSPopUpButtonand populate its menu items (you can do this via the Attributes Inspector or programmatically later) - Add an empty
NSViewto act as a container for your dynamic views. Name itcontentContainerViewand link it to your main view controller as anIBOutlet. - Link the
NSPopUpButtonto your main controller as anIBOutlet, then set its action to a method likepopupSelectionChanged(_:).
3. Implement the Selection Change Logic
In your main view controller class:
First, declare variables to hold your child view controllers (so you don't recreate them every time selection changes):
private var currentChildVC: NSViewController? private let item1VC = Item1ViewController(nibName: "Item1ViewController", bundle: nil) private let item2VC = Item2ViewController(nibName: "Item2ViewController", bundle: nil)
Next, implement the action method that triggers when the popup selection changes:
@IBAction func popupSelectionChanged(_ sender: NSPopUpButton) { // Remove the currently displayed child view and controller currentChildVC?.view.removeFromSuperview() currentChildVC?.removeFromParent() // Pick the right view controller based on the selected item let selectedVC: NSViewController switch sender.selectedItem?.title { case "Item 1": selectedVC = item1VC case "Item 2": selectedVC = item2VC default: selectedVC = item1VC // Fallback to a default view } // Add the new child view controller to the container addChild(selectedVC) selectedVC.view.frame = contentContainerView.bounds // Ensure the child view resizes with the container selectedVC.view.autoresizingMask = [.width, .height] contentContainerView.addSubview(selectedVC.view) currentChildVC = selectedVC }
4. Set the Initial View
Don't forget to show a default view when your main controller loads. Add this to viewDidLoad():
override func viewDidLoad() { super.viewDidLoad() // Show Item 1 by default (replace `popUpButton` with your IBOutlet name) popupSelectionChanged(popUpButton) }
Bonus Tips
- If you prefer Auto Layout over autoresizing masks, replace the frame and autoresizing lines with:
selectedVC.view.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ selectedVC.view.topAnchor.constraint(equalTo: contentContainerView.topAnchor), selectedVC.view.leadingAnchor.constraint(equalTo: contentContainerView.leadingAnchor), selectedVC.view.trailingAnchor.constraint(equalTo: contentContainerView.trailingAnchor), selectedVC.view.bottomAnchor.constraint(equalTo: contentContainerView.bottomAnchor) ]) - To populate the popup button programmatically, add this to
viewDidLoad():popUpButton.addItem(withTitle: "Item 1") popUpButton.addItem(withTitle: "Item 2") - Double-check that all your Nib files are included in your Bundle target (in Xcode's "Build Phases" > "Copy Bundle Resources") to avoid loading errors.
内容的提问来源于stack exchange,提问作者Mohit

