2

I'm a complete noob at macOS UI programming. Last time I did that was sometime in the 20th century using Visual Mac Standard Basic or REALbasic…

I'm trying to build a graphical UI to interact with some algorithms written in Swift using SwiftUI. I don't intend on distributing a runnable application bundle, instead the GUI should be launched from the command line using swift run or similar.

I've managed to get a window with my UI shown on the screen but it doesn't really behave. It doesn't get focus when running the executable from the command line and clicking the window makes it look like the frontmost window but the window from Terminal.app still has the focus and receives keystrokes. There's no app icon in the Dock (even a generic one) and I can't switch to the application using Command-Tab.

What am I missing to get the usual behaviour from the application in this regard?

I'm using macOS 10.15.7 and Xcode 12.4. I want the application to be build using the Swift Package Manager from the command line. Below are the files from the minimal project I'm woking with:

Package.swift
// swift-tools-version:5.3 import PackageDescription let linkerFlags = [ "-Xlinker", "-sectcreate", "-Xlinker", "__TEXT", "-Xlinker", "__info_plist", "-Xlinker", "Resources/Info.plist"] let package = Package( name: "ConnectedRegions", platforms: [.macOS(.v10_15)], products: [ .executable(name: "ConnectedRegions", targets: ["ConnectedRegions"])], targets: [ .target( name: "ConnectedRegions", linkerSettings: [.unsafeFlags(linkerFlags)])]) 
Info.plist
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>NSPrincipalClass</key> <string>NSApplication</string> </dict> </plist> 
main.swift
import Cocoa import SwiftUI class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { let window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 200, height: 200), styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView], backing: .buffered, defer: false) window.center() window.contentView = NSHostingView(rootView: Text("Hello").padding(50)) window.makeKeyAndOrderFront(nil) } } let delegate = AppDelegate() NSApplication.shared.delegate = delegate _ = NSApplicationMain(CommandLine.argc, CommandLine.unsafeArgv) 
1
  • I would suggest creating a macOS app project using SwiftUI in Xcode and the adding your existing code to that project. Commented Aug 22, 2021 at 20:01

1 Answer 1

6

With the new App protocol from SwiftUI in macOS 11, which provides an entry point, this is quite easy to achieve. No Info.plist is necessary to get a default menu and Dock icon:

import SwiftUI @main struct MyApp: App { @NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate var body: some Scene { WindowGroup { VStack { Button("Done") { exit(0) } } .padding(100) } } } class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ notification: Notification) { NSApplication.shared.setActivationPolicy(.regular) NSApplication.shared.activate(ignoringOtherApps: true) } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.