Как использовать IndexSet для поиска элемента в пользовательской структуре

#ios #swift #swiftui #swiftui-list #nsindexset

#iOS #swift #swiftui #swiftui-список #nsindexset

Вопрос:

Я пытаюсь использовать .delete метод SwiftUI в списке, чтобы определить, что HKWorkout пользователь пытается удалить, но поскольку я упаковываю свои тренировки в пользовательский объект WorkoutMonth, мне трудно понять, как я могу углубиться в конкретную тренировку, на которую нажимает пользователь? 🤔 В UIKIT я смог использовать indexPath.section и indexPath.row найти его, но здесь я потерялся.

 struct MonthsWorkoutsListView: View {
    
    
    @Environment(.colorScheme) var colorScheme
    @EnvironmentObject var trackerDataStore: TrackerDataStore
    @State var workouts: [TrackerWorkout]
    @State var workoutMonths = [WorkoutMonth]()
    
    var body: some View {
        VStack {
            if workoutMonths.count == 0 {
                Text("No workouts logged yet.  Open the Athlytic App on your Apple Watch to start and save a new workout.")
                    .multilineTextAlignment(.center)
                    .padding(.horizontal)
            } else {
                List {
                    ForEach(workoutMonths) { workoutMonth in
                        Section(header: Text(getFormattedYearMonth(workoutMonth: workoutMonth))) {
                            ForEach(workoutMonth.trackerWorkouts) { workout in
                                NavigationButton(
                                    action: {
                                        trackerDataStore.selectedWorkout = workout //this line is needed so that the image  at the top of WorkoutDetailHeaderCard gets updated,  otherwise the view loads before the async called and you end up with the  image of the last selected workout
                                        trackerDataStore.loadDataForSelectedWorkout(selectedWorkoutToBeUpdated: workout)
                                    },
                                    destination: {
                                        WorkoutDetailView().environmentObject(trackerDataStore)
                                    },
                                    workoutRow: { WorkoutRow(trackerWorkout: workout) }
                                )
                            }
                        }
                    }
                    .onDelete(perform: delete)
                }
                .navigationBarTitle(Text("Workouts"))
            }
        }
        .onAppear {
            workoutMonths = buildWorkoutsIntoYearMonths(workouts: workouts)
        }
    }
    
    func delete(at offsets: IndexSet) {

        //How to look up the workout user wants to delete?

    }

struct YearMonth: Comparable, Hashable {
    
    let year: Int
    let month: Int
    
    init(year: Int, month: Int) {
        self.year = year
        self.month = month
    }
    
    init(date: Date) {
        let comps = Calendar.current.dateComponents([.year, .month], from: date)
        self.year = comps.year!
        self.month = comps.month!
    }
    
    static func < (lhs: YearMonth, rhs: YearMonth) -> Bool {
        if lhs.year != rhs.year {
            return lhs.year < rhs.year
        } else {
            return lhs.month < rhs.month
        }
    }
}

struct WorkoutMonth: Identifiable {
    var id = UUID()
    var yearMonth: YearMonth
    var trackerWorkouts: [TrackerWorkout]
}
 

Ответ №1:

Вы IndexSet передали в качестве параметра. Это можно использовать для удаления правильных тренировок

 workoutMonths.remove(atOffsets: offsets)
 

Если вы хотите собрать все объекты, которые должны быть удалены, вы также можете выполнить итерацию, используя цикл foreach . Затем вы получаете доступ к каждому из объектов, которые будут удалены.

 for offset in offsets {
   var workoutMonth: WorkoutMonth = workoutMonths[offset]
}
 

Комментарии:

1. Я не могу просто использовать .remove(atOffsets) , потому что мне нужно позвонить. удаление при тренировке в API HealthKit от Apple. И я не могу использовать 2-й пример, потому что я не знаю, сколько существует смещений.

2. @GarySabo зачем вам нужно знать точное количество? разве недостаточно только для каждого? На нем также доступно количество. Я не совсем понимаю проблему. Если вам нужны точные объекты тренировки — лучше всего использовать для каждого цикла, создайте массив этих удаленных объектов, а затем удалите их из HealthKit API как коллекцию объектов

3. Мне нужен доступ к тренировке. Проблема в том, что у меня есть доступ к тренировке в ForEach(workoutMonth.trackerWorkouts) { workout in правильном, но my .delete находится за пределами этого цикла, поэтому у меня нет его для передачи HKHealthStore.delete(workout)

Ответ №2:

Я понял это, у меня был свой .delete внешний forEach вид, и размещение его здесь дало мне доступ к workoutMonth

 ForEach(workoutMonth.trackerWorkouts) { workout in
    NavigationButton(
        action: {
            trackerDataStore.selectedWorkout = workout
            trackerDataStore.loadDataForSelectedWorkout(selectedWorkoutToBeUpdated: workout)
        },
        destination: {
            WorkoutDetailView().environmentObject(trackerDataStore)
        },
        workoutRow: { WorkoutRow(trackerWorkout: workout) }
    )
}
.onDelete { (offSets) in
    for offset in offSets {
    print("user wants to delete workout (workoutMonth.trackerWorkouts[offset].startDate)")
    }
}