Adding a menu item to open a URL

Hello. I'm new to Swift and am attempting to create a menu item on the menu bar that will open a URL in the default browser. When I run this code, I get the error message "NSMenu has no member URL" but I'm not sure what I'm doing wrong.

  func setupMenus() {
       
       let menu = NSMenu()
      _ = URL(string: "https://www.example.com")

       menu.addItem(NSMenuItem.separator())

      if #available(macOS 12.0, *) {
          menu.addItem(NSMenuItem(title: "Example", action: #selector(NSMenu.URL), keyEquivalent: ""))
      } else {
          // Fallback on earlier versions
      }

       statusItem.menu = menu
   }

Hey, maybe this could help you:

Code example
import Cocoa

func main() {
    let delegate = AppDelegate()
    let app = NSApplication.shared
    app.delegate = delegate
    app.setActivationPolicy(.prohibited)
    app.run()
}

final class AppDelegate: NSObject, NSApplicationDelegate {
    
    var item: NSStatusItem!
    var status: NSStatusBar!
    var processInfo: ProcessInfo!
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        status = NSStatusBar.system
        
        item = status.statusItem(withLength: NSStatusItem.variableLength)
        item.behavior = [.removalAllowed, .terminationOnRemoval]
        item.button!.image = NSImage(systemSymbolName: "leaf.fill", accessibilityDescription: "Low Power Mode")
        item.isVisible = true
        
        item.button!.action = #selector(toggleState)
        
        processInfo = ProcessInfo()
        
        if processInfo.isLowPowerModeEnabled {
            item.button!.appearsDisabled = false
        } else {
            item.button!.appearsDisabled = true
        }
        
    }
    
    @objc
    func toggleState() {
        if processInfo.isLowPowerModeEnabled {
            try! zsh("sudo pmset -a lowpowermode 0")
            item.button!.appearsDisabled = true
        } else {
            try! zsh("sudo pmset -a lowpowermode 1")
            item.button!.appearsDisabled = false
        }
    }
    
}

It's part of a tiny utility that toggles low power mode from the status bar, it should work in a very similar way :slight_smile:

What you're essentially doing here is using Swift to work with Objective-C so it's going to be a bit weird. It's not really a Swift question, more an Apple API question that is better asked on the Apple Developer Forums.


Still,
action is expecting you to give it an @objc function that it's supposed to call.


I had a look at the api, you should try this:

@objc
func openURL() {
    NSWorkspace.shared.open(URL(string: "https://google.com/")!)
}

and pass it with the selector #selector(openURL)

Especially when learning, I would avoid the old obj-c apis and use SwiftUI :wink:

Thank you TeamPuzel! That last bit of code you included worked perfectly! I'll also take a look at the additional blocks as well. Thanks again!

2 Likes