Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
667 views
in Technique[技术] by (71.8m points)

ios - SwiftUI @Binding property not updating nested views - Xcode 12

I have problems updating my nested SwiftUI views with @Binding property. I declared a DataModel with ObservableObject protocol:

class DataModel: ObservableObject {
    
    @Published var subjects: [Subject] = []
    ...
}

I added it to my main app:

@main
struct LessonToTextApp: App {
    
    @ObservedObject private var data = DataModel()
    
    var body: some Scene {
        WindowGroup {
            NavigationView {
                SubjectsView(subjects: $data.subjects) {
                    data.save()
                }
            }
            .onAppear {
                data.load()
            }
        }
    }
}

I passed the Subjects array to the first view

struct SubjectsView: View {
    
    @Binding var subjects: [Subject]

    var body: some View {
        List {
            if subjects.isEmpty {
                Text("subjects.empty")
            } else {
                
                ForEach(subjects) { subject in
                    NavigationLink(destination: DetailView(subject: binding(for: subject), saveAction: saveAction)) {
                        CardView(subject: subject)
                    }
                    .listRowBackground(subject.color)
                    .cornerRadius(10)
             }
        }
}

        private func binding(for subject: Subject) -> Binding<Subject> {
               guard let subIndex = subjects.firstIndex(where: { $0.id == subject.id }) else {
                    fatalError("Can't find subject in array")
               }
               return $subjects[subIndex]
         }

And then i passed the single subject to the Second view using the function binding declared above:


struct DetailView: View {
     
    @Binding var subject: Subject

    var body: some View {
         ForEach(subject.lessons) { lesson in
                NavigationLink(destination: LessonView(lesson: lesson)) {                                    
                    Text(lesson.date, style: .date)
                }
         }
         .onDelete { indexSet in
                self.subject.lessons.remove(atOffsets: indexSet)
          }
     }

In the DetailView, when i delete an item in ForEach the item still appear, the view doesn't update.

I'm using SwiftUI 2.0 on Xcode 12.3 (12C33)

EDIT This is the Model:

struct Subject: Identifiable, Codable {
    let id: UUID
    var name: String
    var teacher: String
    var color: Color
    var lessons: [Lesson]
}

struct Lesson: Identifiable, Codable {
    let id: UUID
    let date: Date
    var lenghtInMinutes: Int
    var transcript: String
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Your SubjectsView should take in the entire DataModel as an @EnvironmentObject

struct LessonToTextApp: App {

@StateObject private var data = DataModel()

var body: some Scene {
    WindowGroup {
        NavigationView {
            SubjectsView().environmentObject(data) {
                data.save()
            }
            ...

struct SubjectsView: View {

@EnvironmentObject var data = DataModel

var body: some View {
    List {
        if data.subjects.isEmpty {
            Text("subjects.empty")
            ...

Also, struct are immutable

class Subject: Identifiable, Codable, ObservableObject {
    let id: UUID
    @Published var name: String
    @Published var teacher: String
    @Published var color: Color
    ...
}

struct DetailView: View {
 
    @ObservedObject var subject: Subject

    var body: some View {
    ...

That way you can get to the DetailView with

DetailView(subject: subject)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...