Why does the EditButton says "Done" (instead of "Edit") after I delete one scrum using "swipe to delete"?
I tried changing editMode to .inactive inside onDelete, but even this didn't work.
Why is this not working, and can I fix it somehow? Is it some new bug?
struct ScrumsView: View {
@Binding var scrums: [DailyScrum]
@Environment(\.scenePhase) private var scenePhase
@State private var isPresentingNewScrumView = false
@State private var newScrumData = DailyScrum.Data()
let saveAction: ()->Void
var body: some View {
List {
ForEach($scrums) { $scrum in
NavigationLink(destination: DetailView(scrum: $scrum)) {
CardView(scrum: scrum)
}
.listRowBackground(scrum.theme.mainColor)
}
.onDelete { indexSet in
scrums.remove(atOffsets: indexSet)
}
}
.navigationTitle("Daily Scrums")
.toolbar {
ToolbarItemGroup(placement: .navigationBarLeading) {
EditButton()
}
ToolbarItemGroup(placement: .navigationBarTrailing) {
Button {
isPresentingNewScrumView = true
} label: {
Image(systemName: "plus")
}
.accessibilityLabel("New scrum")
}
}
.sheet(isPresented: $isPresentingNewScrumView) {
NavigationView {
DetailEditView(data: $newScrumData)
//.navigationTitle(Text("New Scrum"))
.toolbar {
ToolbarItemGroup(placement: .cancellationAction) {
Button("Dismiss") {
isPresentingNewScrumView = false
newScrumData = DailyScrum.Data()
}
}
ToolbarItemGroup(placement: .confirmationAction) {
Button("Add") {
let newScrum = DailyScrum(data: newScrumData)
scrums.append(newScrum)
isPresentingNewScrumView = false
newScrumData = DailyScrum.Data()
}
}
}
}
}
.onChange(of: scenePhase) { phase in
if phase == .inactive { saveAction() }
}
}
}
CodePudding user response:
It seems EditButton
is incompatible with this new way of using @StateObject
to declare the store object. I had the idea to try reverting to the old way of creating the store object and surprisingly it fixed the issue. Change the ScrumStore
to this
class ScrumStore: ObservableObject {
@Published var scrums: [DailyScrum] = []
static var shared = ScrumStore()
And change the ScrumdingerApp
to this:
struct ScrumdingerApp: App {
private var store = ScrumStore.shared
var body: some Scene {
WindowGroup {
NavigationView {
ScrumsView(store: store) {
And ScrumsView
to this:
struct ScrumsView: View {
//@Binding var scrums: [DailyScrum]
@ObservedObject var store: ScrumStore
...
var body: some View {
List {
ForEach($store.scrums) { $scrum in
And change the other scrums
to store.scrums
too.
This makes the edit button work properly for swipe to delete
I would also improve the code by making the store object be an Environment object, e.g.
struct ScrumdingerApp: App {
private var store = ScrumStore.shared
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(store)
}
}
struct ContentView: View {
@EnvironmentObject var store: ScrumStore
...
I would also improve how the model structs are loaded and saved, e.g. I would load it in the object's init and have a function to save it. The function could be called on a scene phase or after the model is mutated. Before doing too much loading and saving you might want to try FileDocument
which does all that for you and gives you iCloud drive support for free. I recommend the document app WWDC videos to learn that, there is a new one every year.