如何在 macOS 上的 SwiftUI 中从边栏列表中干净地删除元素

How do I cleanly delete elements from a Sidebar List in SwiftUI on macOS

我想为用户提供从 macOS 中 SwiftUI 应用侧边栏中删除 List 元素的选项。

这是我目前拥有的:

import Foundation
import SwiftUI

@main
struct FoobarApp: App {

    @StateObject private var modelData = ModelData()

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(modelData)
        }
        .commands {

        }
    }
}

class ModelData: ObservableObject {
    @Published var myLinks = [URL(string: "https://google.com")!, URL(string: "https://apple.com")!, URL(string: "https://amazon.com")!]
}


struct ContentView: View {

    @EnvironmentObject var modelData: ModelData

    @State private var selected: URL?

    var body: some View {
        NavigationView {

            List(selection: $selected) {
                Section(header: Text("Bookmarks")) {

                    ForEach(modelData.myLinks, id: \.self) { url in
                        NavigationLink(destination: Text("Viewing detailed data for: \(url)") ) {
                            Text(url.absoluteString)
                        }
                        .tag(url)
                    }

                }
            }
            .onDeleteCommand {
                if let selection = selected {
                    modelData.myLinks.remove(at: modelData.myLinks.firstIndex(of: selection)!)
                }
            }
            .toolbar {
                Button("Selected") {
                    print(selected ?? "Nothing selected")
                }
            }

            Text("Choose a link")

        }
        .frame(minWidth: 200, minHeight: 500)
    }
}

当我 select 侧边栏之一 link 并按下键盘上的 delete 按钮时,link 会被删除,但详细视图不会'总是被清除。

这是我所指内容的 gif:

我希望详细视图在用户删除 link 后恢复为默认文本 Choose a link。有办法解决这个问题吗?

此外,我注意到在 link 被删除后 ContentView.selected 没有被清除。这是预期的吗? (我包含了一个 Selected 按钮来打印这个变量的内容)

我正在使用 macOS 12.2.1 & Xcode 13.2.1.

提前致谢。

这不起作用的原因是,当侧边栏中的状态发生变化时,右侧的 Destinationview 不会更新。将逻辑移动到视图模型并创建一个指定的视图,其中包含 UI 的详细信息。

  1. 将选定的变量移动到您的视图模型:

    class ModelData: ObservableObject {
     @Published var myLinks = [
         URL(string: "https://google.com")!,
         URL(string: "https://apple.com")!,
         URL(string: "https://amazon.com")!]
     @Published var selected: URL?
    }
    
  2. 为目的地创建新视图:

    struct DestinationView: View{
     @EnvironmentObject var modelData: ModelData
     var body: some View{
    
         if let selected = modelData.selected{
             Text("Viewing detailed data for: \(selected)")
         }else{
             Text("Choose a link")
         }
     }
    }
    
  3. 更改导航视图目的地:

    NavigationLink(destination: DestinationView() ) {
        Text(url.absoluteString)
    }
    
  4. 更改您的 ondelete 修饰符:

     if let selection = modelData.selected {
        modelData.myLinks.remove(at: modelData.myLinks.firstIndex(of: selection)!)
     }
     modelData.selected = nil