Search code examples
swiftuinullmodal-dialogactionswipe

Multiple sheet(item: ) triggered by SwipeActions button and ToolBar buttons gets nil object in the first time in SwiftUI


I am using swipeActions in ForEach loop of a List and toolbar buttons to show different sheets on my SwiftUI view. But every first time I swipe left and click the Edit button, the object of that line is nil. If I do the same swipe and click thing again, everything goes well. Anyone else had this kind of bug before? Thank you.

Here is the related code:

struct LanguagesView: View {

@State var activeSheet: ActiveSheet?
@State var toBeEdit: MeLanguage?
   
var body: some View {
    NavigationView {
        List {
            ForEach(self.meLanguages, id: \.id) { lan in                   
                    HStack {
                        Text("\(lan.wrappedName)")
                            .font(.headline)
                    }.swipeActions(allowsFullSwipe: false) {
                        Button(
                            action: {
                                self.activeSheet = .editLanguage
                                self.toBeEdit = lan
                            },
                            label: { Label("Edit", systemImage: "pencil") }
                        ) .tint(.indigo)
                    }
            }
        }
        .sheet(item: $activeSheet,
               onDismiss: {
            self.toBeEdit = nil
        }
         ){
             item in
             switch item {
             case .addLanguage:
                 AddLanguage()
             case .sortLanguages:
                 SortLanguagesView()
             case .editLanguage:
                 if self.toBeEdit != nil {
                     EditLanguageView( meLanguage: self.toBeEdit! )
                 }
                 else {
                     Text("self.toBeEdit is nil")
                 }
             default:
                 Text("No such button on ContentView.")
             }
         }
        
        .toolbar {
            ToolbarItemGroup {
                HStack {
                    Text("\(self.meLanguages.count) Languages on Card").font(.headline)
                    self.barButtons
                }
            }
        }
    }
}
var barButtons: some View {
    HStack {
        
        Button(
            action: {
                self.activeSheet = .sortLanguages
            },
            label: { Label("Sort Languages", systemImage: "arrow.up.arrow.down.circle")
            }
        ).id("sortLanguages")
        
        Button(
            action: {
                self.activeSheet = .addLanguage
            },
            label: { Label("Add Language",
                systemImage: "plus")
                    .imageScale(.large)
            }
        )
    }
}

}

If I only think of the sheet triggered by swipeActions Edit button, the code below works perfectly. But I still need other sheets triggered by ToolBar buttons.

 .sheet(item: self.$toBeEdit, content: { toBeEdit in
                EditLanguageView( meLanguage: toBeEdit)                        
            })

Solution

  • After more searching I realised it's not something about SwipeActions. This is actually similar to this question:

    SwiftUI presenting sheet with Binding variable doesn't work when first presented

    So I added an hidden Text after the ForEach loop and the problem solved.

    ForEach(self.meLanguages, id: \.id) { ... }
    if self.toBeEdit != nil {
                        Text("\(self.toBeEdit!.wrappedName)").hidden()
                    }