我正在使用
SwiftUI
和新的 App
生命周期构建 macOS 应用程序。
我很想更改“关于窗口”的内容(当您点击应用程序菜单中的“关于 DemoApp”时出现),但不知道如何更改:
如何将“关于”视图替换为自定义视图?
你可以这样做,但它确实需要创建一个 AppDelegate。您的 AppFile 应该如下所示:
struct MyApp: App {
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
MainView()
}
.commands {
CommandGroup(replacing: CommandGroupPlacement.appInfo) {
Button(action: {
appDelegate.showAboutPanel()
}) {
Text("About My App")
}
}
}
}
}
你的 AppDelegate 应该是这样的:
class AppDelegate: NSObject, NSApplicationDelegate {
private var aboutBoxWindowController: NSWindowController?
func showAboutPanel() {
if aboutBoxWindowController == nil {
let styleMask: NSWindow.StyleMask = [.closable, .miniaturizable,/* .resizable,*/ .titled]
let window = NSWindow()
window.styleMask = styleMask
window.title = "About My App"
window.contentView = NSHostingView(rootView: AboutView())
aboutBoxWindowController = NSWindowController(window: window)
}
aboutBoxWindowController?.showWindow(aboutBoxWindowController?.window)
}
}
然后,只需创建一个名为 AboutView 的 SwiftUI 视图,它就会在您的“关于”框中显示该视图。例如:
struct AboutView: View {
var body: some View {
VStack {
Spacer()
HStack {
Spacer()
Text("Hello, World!")
Spacer()
}
Spacer()
}
.frame(minWidth: 300, minHeight: 300)
}
}
import Foundation
import SwiftUI
struct AboutView: View {
var body: some View {
VStack(spacing: 10) {
Image(nsImage: NSImage(named: "AppIcon")!)
Text("\(Bundle.main.appName)")
.font(.system(size: 20, weight: .bold))
// Xcode 13.0 beta 2
//.textSelection(.enabled)
Link("\(AboutView.offSiteAdr.replace(of: "http://", to: ""))", destination: AboutView.offCiteUrl )
Text("Ver: \(Bundle.main.appVersionLong) (\(Bundle.main.appBuild)) ")
// Xcode 13.0 beta 2
//.textSelection(.enabled)
Text(Bundle.main.copyright)
.font(.system(size: 10, weight: .thin))
.multilineTextAlignment(.center)
}
.padding(20)
.frame(minWidth: 350, minHeight: 300)
}
}
///////////////////////////////////
/// HELPERS
//////////////////////////////////
class AppDelegate: NSObject, NSApplicationDelegate {
private var aboutBoxWindowController: NSWindowController?
func showAboutWnd() {
if aboutBoxWindowController == nil {
let styleMask: NSWindow.StyleMask = [.closable, .miniaturizable,/* .resizable,*/ .titled]
let window = NSWindow()
window.styleMask = styleMask
window.title = "About \(Bundle.main.appName)"
window.contentView = NSHostingView(rootView: AboutView())
window.center()
aboutBoxWindowController = NSWindowController(window: window)
}
aboutBoxWindowController?.showWindow(aboutBoxWindowController?.window)
}
}
extension AboutView {
private static var offSiteAdr: String { "http://www.taogit.com" }
private static var offEmail: String { "[email protected]" }
public static var offCiteUrl: URL { URL(string: AboutView.offSiteAdr )! }
public static var offEmailUrl: URL { URL(string: "mailto:\(AboutView.offEmail)")! }
}
extension Bundle {
public var appName: String { getInfo("CFBundleName") }
//public var displayName: String {getInfo("CFBundleDisplayName")}
//public var language: String {getInfo("CFBundleDevelopmentRegion")}
//public var identifier: String {getInfo("CFBundleIdentifier")}
public var copyright: String {getInfo("NSHumanReadableCopyright").replace(of: "\\\\n", to: "\n") }
public var appBuild: String { getInfo("CFBundleVersion") }
public var appVersionLong: String { getInfo("CFBundleShortVersionString") }
//public var appVersionShort: String { getInfo("CFBundleShortVersion") }
fileprivate func getInfo(_ str: String) -> String { infoDictionary?[str] as? String ?? "⚠️" }
}
并分配给菜单行:
struct MyApp: App {
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
MainView()
}
// Replacement of standard About window
.commands {
CommandGroup(replacing: CommandGroupPlacement.appInfo) {
Button("About \(Bundle.main.appName)") { appDelegate.showAboutWnd() }
}
}
}
}
结果:
奖励:支持“ “版权所有
所以我使用了
hayesk
描述的方法一段时间,但我意识到这可以完全通过SwiftUI UI来完成(不需要应用程序委托)。
struct RoamApp: App {
@Environment(\.openWindow) private var openWindow
var body: some Scene {
Window("Roam", id: "main") {
RemoteView()
}
.commands {
CommandGroup(replacing: CommandGroupPlacement.appInfo) {
Button(action: {
// Open the "about" window
openWindow(id: "about")
}, label: {
Text("About Roam", comment: "Button to open the about page of the Roam app")
})
}
}
// Note the id "about" here
Window("About Roam", id: "about") {
ExternalAboutView()
}
}
}