I have an array that contains the data that is displayed on a list. When the user hits "new", a sheet pops up to allow the user to enter a new item to the list.
I just added a swipe option to edit this item and I wanted to reuse the same sheet to edit the item's text. But I'm having problems understanding how to check whether a specific item was selected (by UUID?) to pass to the sheet, or it's a new item.
Code:
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])
}
}
}
}
My rationale was to check whether self.selectedItemId == NULL was null or not, if not then pass that element to the sheet to be edited, if yes, the as it as a new element.
What am I doing wrong? And if there is a standard way to pass information to the sheet based on whether there is an item select or not, could you show me?
Thanks!
CodePudding user response:
From this post, you can do like this in your case:
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)
}
}
}
}
Note : SheetView does not need any more a boolean, but you can add one if you orefer
CodePudding user response:
Swift uses nil, not null, so the compiler is complaining when you are comparing selected items to null. However, you will have another issue. Your selectedItemId is optional, so you can't just use it in your else clause to make your note. You are better off using an if let to unwrap it. Change it to:
.sheet(isPresented: $sheetIsShowing) {
if let selectedItemId = selectedItemId,
let index = data.notes.firstIndex(where: { $0.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)
}
}
edit:
I realized that you were attempting to use two optionals without unwrapping them, so I changed this to an if let to make sure both are safely unwrapped.
