Mam widok w pętli za pomocą ForEach, aby wyświetlić listę w tablicy przy użyciu relacji danych podstawowych.

Widok pokazuje wszystkie elementy w każdej pętli i muszę je segmentować indywidualnie, jednocześnie będąc w stanie przełączać przycisk i nie przełączać wszystkich celów w tym samym czasie.

Edycja: wymyśliłem, jak to zrobić, aby wszystkie nie były iterowane i pokazywane, ale teraz przełączanie dowolnego z przycisków przełącza je wszystkie. :(

GameGoalDetail

import SwiftUI
import CoreData

struct GameGoalsDetail: View {
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(entity: Game.entity(), sortDescriptors: []) var games: FetchedResults<Game>

    @State private var showingAddGoal = false

    @State private var goalComplete : Bool = false

    @ObservedObject var game: Game

    var body: some View {
        VStack {
            Text(self.game.gameName ?? "No Game Name").font(.title)
            Text(self.game.gameDescription ?? "No Game Description").font(.subheadline)
            List {GameGoalListView(game: self.game).environment(\.managedObjectContext, self.moc)
                }
            Button("Add Game Goal") {
                self.showingAddGoal.toggle()
            }
                .sheet(isPresented: $showingAddGoal) {
                    AddGameGoalsView(game: self.game).environment(\.managedObjectContext, self.moc)
            }
        }
    }
}

GameGoalsListView

import SwiftUI
import CoreData


struct GameGoalListView: View {

    @Environment(\.managedObjectContext) var moc
    @FetchRequest(entity: Game.entity(), sortDescriptors: []) var games: FetchedResults<Game>

    @ObservedObject var game: Game

    @State private var goalComplete : Bool = false


    var body: some View {
        VStack {
            ForEach(game.goalArray, id: \.self) { goal in
                HStack {
                    Text(goal.goalName ?? "No Goal Name")
                    Spacer()
                    Text("Complete:").font(.caption)
                    Image(systemName: self.goalComplete ? "checkmark.square.fill" : "app").onTapGesture {
                        self.goalComplete.toggle()
                        print(self.goalComplete)
                    }
                }
            }
        }

    }
}

Oto zrzut ekranu tego, co się dzieje: Zrzut ekranu wszystkich elementów jest przełączany

Po kliknięciu: Wszystkie elementy przełączane zamiast jednego

Staram się, aby po dodaniu celu pojawił się na liście, a następnie mogę wybrać, czy cel został ukończony, czy nie, za pomocą przycisku. Tak więc każda gra miałaby listę różnych celów, które są dodawane przez dane wejściowe użytkownika.

Naprawdę doceniłbym pomoc i może udzielić dalszych informacji na żądanie.

0
andywalt 3 styczeń 2020, 22:28

1 odpowiedź

Najlepsza odpowiedź

Musiałem tyle tego przerobić, ale z pomocą fantastycznego Redditora udało mi się to rozgryźć.

GameGoalsDetail

  • Nie potrzebowałem żądania pobrania, ponieważ było przekazywane z widoku.
  • Nie potrzebowałem @State, ponieważ powinienem był bezpośrednio używać informacji CoreData.
List {
    ForEach(game.goalArray, id: \.self) { goal in
        GameGoalListView(goal: goal)
    }
}

Potrzebowałem tylko GameGoalListView (goal: goal), ponieważ przeszedłem ponownie GameGoalListView.

GameGoalListView

  • Pozbyłem się ponownie @State i @FetchRequest
  • Lista w GameGoalsDetail pokazuje każdy cel, więc dodatkowe ForEach nie jest potrzebne w tym widoku. Ten widok musiał tylko pokazać to, co trzeba było pokazać, i informacje wyciągnięte z CoreData.

Obiekt @ObservedObject jest celem, a nie grą. OnTapGesture uzyskuje dostęp do goal.goalComplete z CoreData, a nie State (co tworzy nowe Źródło Prawdy (obejrzyj wideo WDCC)).

Następnie onReceive i objectWillChange pozwalają celowi wiedzieć, że zmienia się za każdym razem, gdy przycisk jest dotknięty.

struct GameGoalListView: View {
    
    @Environment(\.managedObjectContext) var moc
    
    @ObservedObject var goal: Goal
    
    var body: some View {
        VStack {
            HStack {
                Text(goal.goalName ?? "No Goal Name")
                Spacer()
                Text("Complete:").font(.caption)
                Image(systemName: self.goal.goalComplete ? "checkmark.square.fill" : "app").onTapGesture {
                    self.goal.goalComplete.toggle()
                    print(self.goal.goalComplete)
                }
            }
        }
        .onReceive(self.goal.objectWillChange) {
            try? self.moc.save()
        }
    }
}

Jak powiedziałem, pomoc przyszła od Redditora i mam nadzieję, że pomoże to komuś dowiedzieć się, co robię, i naprawić ich błąd.

2
Olcay Ertaş 18 lipiec 2020, 22:38