You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI文档型应用能否跳过文件选择器显示自定义问候视图?

如何在Swift文档型应用启动时跳过默认文件选择器并显示自定义问候窗口

不管是iOS还是macOS平台的文档型应用,都可以通过修改启动逻辑来替换默认的文件选择器,展示自定义问候界面。核心思路是:判断应用启动时是否有打开文档的请求,若无则直接加载自定义界面,并在界面中提供新建/打开文档的入口。

iOS平台实现步骤

1. 修改场景初始化逻辑(SceneDelegate)

在SceneDelegate.swift中,通过启动选项判断是否有打开文档的请求,直接设置对应的根视图控制器:

import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        
        let window = UIWindow(windowScene: windowScene)
        self.window = window
        
        // 检查是否有打开文档的URL请求
        if connectionOptions.urlContexts.isEmpty {
            // 加载自定义问候界面
            let greetingVC = GreetingViewController()
            window.rootViewController = greetingVC
        } else {
            // 有文档打开请求时,使用默认文档浏览器
            let docBrowser = DocumentBrowserViewController()
            window.rootViewController = docBrowser
        }
        
        window.makeKeyAndVisible()
    }
}

2. 实现自定义问候界面

创建GreetingViewController,添加新建/打开文档的按钮,并绑定对应逻辑:

import UIKit

class GreetingViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        
        // 新建文档按钮
        let newDocBtn = UIButton(type: .system)
        newDocBtn.setTitle("新建空白文档", for: .normal)
        newDocBtn.titleLabel?.font = .systemFont(ofSize: 18)
        newDocBtn.frame = CGRect(x: 80, y: 250, width: view.bounds.width - 160, height: 50)
        newDocBtn.addTarget(self, action: #selector(showCreateMenu), for: .touchUpInside)
        view.addSubview(newDocBtn)
        
        // 打开文档按钮
        let openDocBtn = UIButton(type: .system)
        openDocBtn.setTitle("打开已有文档", for: .normal)
        openDocBtn.titleLabel?.font = .systemFont(ofSize: 18)
        openDocBtn.frame = CGRect(x: 80, y: 320, width: view.bounds.width - 160, height: 50)
        openDocBtn.addTarget(self, action: #selector(showFilePicker), for: .touchUpInside)
        view.addSubview(openDocBtn)
    }

    @objc private func showCreateMenu() {
        // 切换到文档浏览器并弹出新建菜单
        let docBrowser = DocumentBrowserViewController()
        docBrowser.modalPresentationStyle = .fullScreen
        present(docBrowser, animated: true) {
            docBrowser.presentDocumentCreationMenu(at: nil, animated: true)
        }
    }

    @objc private func showFilePicker() {
        // 切换到文档浏览器并弹出文件选择器
        let docBrowser = DocumentBrowserViewController()
        docBrowser.modalPresentationStyle = .fullScreen
        present(docBrowser, animated: true) {
            docBrowser.presentDocumentPicker(at: nil, animated: true)
        }
    }
}

macOS平台实现步骤

1. 修改应用启动逻辑(AppDelegate)

在AppDelegate.swift中,阻止默认的打开对话框,并加载自定义问候窗口:

import Cocoa

@main
class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        // 阻止默认打开对话框弹出
        NSApp.setActivationPolicy(.regular)
        
        // 创建并显示自定义问候窗口
        let greetingWindow = NSWindow(
            contentRect: NSRect(x: 0, y: 0, width: 400, height: 300),
            styleMask: [.titled, .closable, .miniaturizable],
            backing: .buffered,
            defer: false
        )
        greetingWindow.center()
        greetingWindow.title = "欢迎使用"
        
        let greetingVC = GreetingViewController()
        greetingWindow.contentViewController = greetingVC
        greetingWindow.makeKeyAndOrderFront(nil)
    }

    // 应用重新激活且无可见窗口时,再次显示问候窗口
    func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
        if !flag {
            let greetingWindow = NSWindow(
                contentRect: NSRect(x: 0, y: 0, width: 400, height: 300),
                styleMask: [.titled, .closable, .miniaturizable],
                backing: .buffered,
                defer: false
            )
            greetingWindow.center()
            greetingWindow.title = "欢迎使用"
            
            let greetingVC = GreetingViewController()
            greetingWindow.contentViewController = greetingVC
            greetingWindow.makeKeyAndOrderFront(nil)
        }
        return true
    }
}

2. 实现自定义问候界面

创建GreetingViewController,添加功能按钮并绑定文档操作逻辑:

import Cocoa

class GreetingViewController: NSViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        view.wantsLayer = true
        view.layer?.backgroundColor = NSColor.white.cgColor
        
        // 新建文档按钮
        let newDocBtn = NSButton(title: "新建空白文档", target: self, action: #selector(createNewDocument))
        newDocBtn.frame = NSRect(x: 80, y: 150, width: 240, height: 40)
        view.addSubview(newDocBtn)
        
        // 打开文档按钮
        let openDocBtn = NSButton(title: "打开已有文档", target: self, action: #selector(openDocument))
        openDocBtn.frame = NSRect(x: 80, y: 90, width: 240, height: 40)
        view.addSubview(openDocBtn)
    }

    @objc private func createNewDocument() {
        let savePanel = NSSavePanel()
        // 替换成你自定义的文档类型UTI
        savePanel.allowedContentTypes = [.init("com.yourapp.yourdoctype")]
        savePanel.begin { [weak self] result in
            guard result == .OK, let url = savePanel.url else { return }
            
            let doc = YourDocument() // 替换成你的NSDocument子类
            doc.save(to: url, ofType: savePanel.allowedContentTypes[0].identifier) { success in
                if success {
                    doc.makeWindowControllers()
                    doc.showWindows()
                }
            }
            self?.view.window?.close()
        }
    }

    @objc private func openDocument() {
        let openPanel = NSOpenPanel()
        openPanel.allowedContentTypes = [.init("com.yourapp.yourdoctype")]
        openPanel.begin { [weak self] result in
            guard result == .OK, let url = openPanel.url else { return }
            
            let doc = YourDocument()
            doc.read(from: url, ofType: openPanel.allowedContentTypes[0].identifier) { success in
                if success {
                    doc.makeWindowControllers()
                    doc.showWindows()
                }
            }
            self?.view.window?.close()
        }
    }
}

内容的提问来源于stack exchange,提问作者Bowen Cui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:42:27