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

iPadOS多窗口SwiftUI应用中聚焦值与对象无法随激活窗口更新的问题咨询

iPadOS多窗口SwiftUI应用中聚焦值与对象无法随激活窗口更新的问题咨询

我正在开发一个支持多窗口的SwiftUI应用(采用SwiftUI生命周期),在WindowGroup上通过.commands定义了主菜单命令。应用结构很简单,包含一个带有MasterView和DetailView的NavigationSplitView。

在层级较深的DetailView中,我使用focusedSceneObject和focusedSceneValue来把DetailViewModel和当前选中的Item传递给AppCommands,这样菜单命令就能和当前激活的DetailView交互。

先贴我的DetailView代码:

struct DetailView: View {
    @StateObject private var viewModel: DetailViewModel = .init()
    let item: Item?
    
    var itemTitle: String {
        item?.title ?? "nil"
    }
    
    var body: some View {
        let _ = Self._printChanges()
        Group {
            if let item = item {
                SelectedItemView(viewModel: self.viewModel, item: item)
            } else {
                ContentUnavailableView("Select an Item", systemImage: "list.bullet", description: Text("Choose an item from the list to see its details"))
            }
        }
        .alert(
            "Alert",
            isPresented: self.$viewModel.presentedAlert,
            actions: {
                Button("OK", role: .cancel) {
                    self.viewModel.presentedAlert = false
                }
            },
            message: {
                Text("Presented from detail view with item: \(self.itemTitle)")
            })
        .navigationTitle(item?.title ?? "Detail")
        .onChange(of: self.item) { _, newValue in
            viewModel.updateItem(newValue)
        }
        // 通过@FocusedValue/@FocusedObject向AppCommands传递当前选中的Item和viewModel
        .focusedSceneValue(\.selectedItem, self.item)
        .focusedSceneObject(self.viewModel)
    }
}

接下来是应用的主结构和AppCommands的实现:

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup(id: "main") {
            ContainerView()
        }
        .commands {
            AppCommands()
        }
    }
}

// MARK: - AppCommands
struct AppCommands: Commands {
    @FocusedValue(\.selectedItem) private var selectedItem: Item?
    @FocusedObject private var viewModel: DetailViewModel?
    
    var body: some Commands {
        let _ = print("AppCommands")
        let _ = print("Focused view model: \(pointer(self.viewModel))")
        let _ = print("Focused selectedItem: \(selectedItem?.title ?? "nil")")
        
        CommandGroup(after: .newItem) {
            Button("Focused View Model Command") {
                print("executing command with focused view model: \(pointer(self.viewModel))")
                viewModel?.presentedAlert = true
            }
            .keyboardShortcut(.return, modifiers: [.command])
            
            Button("Selected Item Command") {
                print("executing command with selected item: \(self.selectedItem?.title ?? "nil")")
            }
            .keyboardShortcut(.return, modifiers: [.command, .shift])
        }
    }
}

我的需求很明确:当DetailView显示时,通过主菜单执行命令(或按下快捷键),应该对当前显示的DetailView对应的viewModel执行操作。这个逻辑在Mac上多窗口的情况下完全正常,但在iPad上打开两个分屏窗口(Split View)时,切换激活窗口(点击窗口切换),@FocusedObject和@FocusedValue并不会正确更新为当前激活窗口的Item和viewModel,还是保留着之前窗口的内容。

我已经录屏演示了这个问题,现在想请教大家:

  • 是我的写法哪里有问题吗?
  • 还是这是iPadOS上SwiftUI的一个bug?
  • 有没有什么办法可以解决这个问题,让菜单命令能正确关联当前激活窗口的DetailView数据?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:00:27