选择数组中的现有项或将新项传递给 .sheet

Selecting an existing item on an array or passing a new one to a .sheet

我有一个数组,其中包含显示在列表中的数据。当用户点击“新建”时,会弹出 sheet 以允许用户向列表中输入新项目。

我刚刚添加了一个滑动选项来编辑这个项目,我想重复使用相同的 sheet 来编辑项目的文本。但是我在理解如何检查特定项目是否被 selected(通过 UUID?)传递给 sheet 或它是一个新项目时遇到了问题。

代码:

let dateFormatter = DateFormatter()

struct NoteItem: Codable, Hashable, Identifiable {
    let id: UUID
    var text: String
    var date = Date()
    var dateText: String {
        dateFormatter.dateFormat = "EEEE, MMM d yyyy, h:mm a"
        return dateFormatter.string(from: date)
    }
    var tags: [String] = []
}

struct ContentView: View {
    @EnvironmentObject private var data: DataModel
    @State private var selectedItemId: UUID?
    @State var searchText: String = ""
    @State private var sheetIsShowing = false

    NavigationView {
        List(filteredNotes) { note in
             VStack(alignment: .leading) {
                 //....
                 // not relevant code
             }
             .swipeActions(allowsFullSwipe: false) {
                 Button(action: {
                      selectedItemId = note.id
                      self.sheetIsShowing = true
                 } ) {
                     Label("Edit", systemImage: "pencil")
                 }
             }
        }
        .toolbar {
            // new item
            Button(action: {
                 self.sheetIsShowing = true
            }) {
                 Image(systemName: "square.and.pencil")
            }
        }
        .sheet(isPresented: $sheetIsShowing) {
                if self.selectedItemId == NULL { // <-- this is giving me an error
                    let Note = NoteItem(id: UUID(), text: "New Note", date: Date(), tags: [])
                    SheetView(isVisible: self.$sheetIsShowing, note: Note)
                } else {
                    let index = data.notes.firstIndex(of: selectedItemId)
                    SheetView(isVisible: self.$sheetIsShowing, note: data.notes[index])
                }
            }

    }
}

我的理由是检查 self.selectedItemId == NULL 是否为 null,如果不是,则将该元素传递给 sheet 进行编辑,如果是,则将其作为新元素。

我做错了什么?如果有一种标准方法可以根据是否有项目 select 将信息传递给 sheet,你能告诉我吗?

谢谢!

Swift 使用 nil,而不是 null,因此当您将所选项目与 null 进行比较时,编译器会报错。但是,您将遇到另一个问题。你的 selectedItemId 是可选的,所以你不能只在你的 else 子句中使用它来制作你的 note。你最好使用 if let 来解包它。将其更改为:

    .sheet(isPresented: $sheetIsShowing) {
        if let selectedItemId = selectedItemId,
            let index = data.notes.firstIndex(where: { [=10=].id == selectedItemId }) {
            SheetView(isVisible: self.$sheetIsShowing, note: data.notes[index])

        } else {
            let note = NoteItem(id: UUID(), text: "New Note", date: Date(), tags: [])
            SheetView(isVisible: self.$sheetIsShowing, note: note)

        }
    }

编辑:

我意识到您试图在不展开它们的情况下使用两个可选值,因此我将其更改为 if let 以确保两者都已安全展开。

开始,您可以在您的情况下这样做:

struct SheetForNewAndEdit: View {
    @EnvironmentObject private var data: DataModel
    @State var searchText: String = ""
    // The selected row
    @State var selectedNote: NoteItem? = nil
    @State private var sheetNewNote = false
    // for test :
    @State private var filteredNotes: [NoteItem] = [
        NoteItem(id: UUID(), text: "111"),
        
        NoteItem(id: UUID(), text: "222")];
    
    var body: some View {
        NavigationView {
            List(filteredNotes) { note in
                VStack(alignment: .leading) {
                    //....
                    // not relevant code
                    
                    Text(note.text)
                }
                .swipeActions(allowsFullSwipe: false) {
                    Button(action: {
                        // the action select the note to display
                        selectedNote = note
                    } ) {
                        Label("Edit", systemImage: "pencil")
                    }
                }
            }
            // sheet is displayed depending on selected note
            .sheet(item: $selectedNote, content: {
                note in
                SheetView(note: note)
            })
            // moved tool bar one level (inside navigation view)
            .toolbar {
                // Toolbar item to have toolbar
                ToolbarItemGroup(placement: .navigationBarTrailing) {
                    ZStack {
                        Button(action: {
                            // change bool value
                            self.sheetNewNote.toggle()
                        }) {
                            Image(systemName: "square.and.pencil")
                        }
                    }
                }
            }
            .sheet(isPresented: $sheetNewNote) {
                let Note = NoteItem(id: UUID(), text: "New Note", date: Date(), tags: [])
                SheetView(note: Note)
            }
        }
    }
}

注意:SheetView 不再需要布尔值,但如果您需要,可以添加一个