我已经配置了我的应用程序,以便可以通过在运行时检查环境变量来在 GUI 模式或 CLI 模式下运行它。
我已经让它工作了,至少在表面上是这样,但是 GUI 版本 (SwiftUI) 似乎并没有与父进程绑定,因此父进程立即终止,并使 SwiftUI 窗口成为孤立的。实际上,这意味着应用程序的某些部分(尤其是异步内容)无法正常工作。
关于我做错了什么有什么想法吗?网络上从
main()
显式调用 SwiftUI 应用程序的示例并不多,所以我主要是跟着我的鼻子写的。
这是代码:
@main
struct CourierApp {
static func main() async throws {
guard let launchMode = ProcessInfo.processInfo.environment["LAUNCH_MODE"], launchMode == "GUI" else {
try await launchCLI()
return
}
try await launchGUI()
}
private static func launchCLI() async throws {
guard var courierCLI = try? CourierCLI.parse(ProcessInfo.processInfo.arguments) else {
throw ValidationError("Invalid arguments. You should invoke Courier providing first your archive and then the output directory for the program. Optionally, some flags can be provided - see the manual for details.")
}
try await courierCLI.run()
}
private static func launchGUI() async throws {
await CourierGUI.main()
}
}
struct CourierCLI: AsyncParsableCommand {
@Argument var archivePath: String
@Argument var outputPath: String
@Flag var uploadToAppStoreConnect = false
@Option(name: [.customShort("e"), .customLong("entitlements")]) var overrideEntitlements: String? = nil
mutating func run() async throws {
}
func validate() throws {
if let overrideEntitlements {
let arrayEntitlements = overrideEntitlements.split(separator: ",")
guard arrayEntitlements.count <= 2 else {
throw ValidationError("When passing entitlements to override, you must provide a comma-delimited list of entitlements, taking care to only include entitlements to grant - any omitted will not be granted to the app. Example: 'tracking,bluetooth'.")
}
}
}
}
struct CourierGUI: App {
var body: some Scene {
WindowGroup {
MasterView()
.navigationTitle("Courier")
}
.defaultPosition(.center)
}
}
可以使用 main.swift 手动调用 CourierApp.main()。 从
@main
中删除 struct CourierApp
注释并创建 main.swift:
if shouldLaunchGUI {
CourierApp.main()
return
} else {
guard var courierCLI = try? CourierCLI.parse(ProcessInfo.processInfo.arguments) else {
return
}
courierCLI.run()
}