SwiftUI macOS应用:如何默认启用主菜单中的Refresh菜单项?
Hey there, let's break down why your Refresh menu item is disabled by default and how to fix it.
The root issue here is that you've tied the menu item to the First Responder's reloadFromOrigin method. Menu items linked to the First Responder only enable when the current first responder (the focused element in your app) actually implements that method. When your app launches, the first responder isn't your WKWebView—so the menu item stays disabled until you click the web view (making it the first responder).
Here are a few solid solutions to get the Refresh item enabled by default, depending on your needs:
1. Directly Bind the Menu Item to Your WKWebView Instance
This is the most straightforward fix. Instead of relying on the First Responder, point the menu item directly at your WKWebView's reloadFromOrigin method. That way, the menu item will be enabled as long as the web view exists, regardless of which element is the first responder.
Steps to implement:
- First, make sure you have a strong reference to your WKWebView in your view controller (or wherever you're managing it):
class YourViewController: NSViewController { var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() webView = WKWebView(frame: view.bounds) view.addSubview(webView) // Load your initial URL webView.load(URLRequest(url: URL(string: "https://your-url.com")!)) } } - Then, update the menu item's target to point directly at this web view. If you created the menu item in code:
If you created the menu item in Storyboard/XIB, set the target in your view controller's// In your menu setup code (e.g., AppDelegate or view controller) if let fileMenu = NSApplication.shared.mainMenu?.item(withTitle: "File")?.submenu, let viewController = NSApplication.shared.mainWindow?.contentViewController as? YourViewController { let refreshItem = NSMenuItem(title: "Refresh", action: #selector(WKWebView.reloadFromOrigin), keyEquivalent: "r") refreshItem.target = viewController.webView fileMenu.addItem(refreshItem) }viewDidLoad:override func viewDidLoad() { super.viewDidLoad() // ... web view setup if let refreshItem = NSApplication.shared.mainMenu?.item(withTitle: "File")?.submenu?.item(withTitle: "Refresh") { refreshItem.target = webView } }
2. Force WKWebView to Be the First Responder on Launch
If you want to stick with the First Responder approach, you can make your WKWebView the first responder as soon as the view appears. This will enable the menu item right away.
Add this to your view controller:
override func viewDidAppear() { super.viewDidAppear() webView.becomeFirstResponder() }
Note: This works, but if the user clicks another focusable element (like a text field), the menu item will disable again unless that element also implements reloadFromOrigin (which it probably won't). So this is less ideal if you want the menu item to stay enabled regardless of focus.
3. Manually Validate the Menu Item
You can take control of the menu item's enabled state by overriding validateMenuItem in your view controller. This lets you decide when the item should be enabled, even if the First Responder doesn't handle the action.
Steps:
- Set the menu item's target to your view controller (instead of First Responder) in Storyboard/XIB or code.
- Add this override to your view controller:
override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool { if menuItem.action == #selector(WKWebView.reloadFromOrigin) { // You can add extra checks here, like if the web view has loaded content return webView != nil } return super.validateMenuItem(menuItem) } - Then, implement the reload action in your view controller to forward it to the web view:
@objc func reloadFromOrigin() { webView.reloadFromOrigin() }
Recommendation
I'd go with option 1—it's the cleanest solution and ensures the Refresh menu item stays enabled as long as your web view exists, no matter what's focused in the app.
内容的提问来源于stack exchange,提问作者esaruoho

