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

基于NSDocument的应用为何偶尔无法打开全部窗口?

解决NSDocument多窗口偶尔只显示一个的问题

我之前做NSDocument多窗口应用时也碰到过类似的随机失效问题,结合你的代码来看,主要有几个可能的原因和对应的解决办法:

1. 修正Storyboard SceneIdentifier的写法

你的代码里用了NSStoryboard.sceneidentifier(),但Swift中正确的写法是**NSStoryboard.SceneIdentifier()**(注意首字母大写的SceneIdentifier,这是枚举类型的静态成员)。写法错误会导致控制器实例化失败返回nil,自然不会显示对应的窗口。

修正后的实例化代码:

let wc = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("WindowController")) as! NSWindowController
wc.contentViewController = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(sceneidentifier[x])) as? NSViewController

2. 显式触发窗口显示

虽然addWindowController(_:)理论上会让NSDocument管理窗口显示,但快速添加多个窗口控制器时,AppKit偶尔会漏掉自动显示逻辑。建议添加后手动调用showWindow(_:)确保窗口弹出:

self.addWindowController(wc)
wc.showWindow(self) // 显式要求窗口显示

3. 添加错误处理排查实例化失败

为了确认是不是某个控制器实例化失败导致窗口缺失,可以加上guard语句捕获错误,方便调试:

override func makeWindowControllers() { 
    let storyboard = NSStoryboard(name: NSStoryboard.Name("Main"), bundle: nil) 
    let sceneIdentifiers : [String] = [ "si1", "si2" ] 
    for x in 0..<sceneIdentifiers.count { 
        // 确保WindowController实例化成功
        guard let wc = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier("WindowController")) as? NSWindowController else {
            print("❌ 无法实例化WindowController")
            continue
        }
        // 确保内容ViewController实例化成功
        guard let contentVC = storyboard.instantiateController(withIdentifier: NSStoryboard.SceneIdentifier(sceneIdentifiers[x])) as? NSViewController else {
            print("❌ 无法实例化内容控制器:\(sceneIdentifiers[x])")
            continue
        }
        wc.contentViewController = contentVC
        self.addWindowController(wc)
        wc.showWindow(self)
    } 
}

4. 排除窗口重叠的假象

有时候窗口其实已经创建,但默认位置完全重叠,看起来像是只显示了一个。可以给每个窗口设置偏移位置验证:

if let window = wc.window {
    // 每个窗口向右下偏移20pt,避免重叠
    let offset = CGFloat(x * 20)
    let newOrigin = CGPoint(x: window.frame.origin.x + offset, y: window.frame.origin.y - offset)
    window.setFrameOrigin(newOrigin)
}

按照上面的步骤调整后,应该就能解决随机只显示一个窗口的问题了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:49:49