SwiftUI - Indexset для индексации в массиве - PullRequest
1 голос
/ 23 января 2020

Я использую ForEach в NavigationView и список в сочетании с функцией, вызываемой, когда пользователь удаляет строку с помощью .onDelete (), как показано ниже.

struct PeriodListView: View {
@ObservedObject var theperiodlist = ThePeriodList()
@EnvironmentObject var theprofile: TheProfile

@State private var showingAddPeriod = false

var dateFormatter: DateFormatter {
    let formatter = DateFormatter()
    formatter.dateStyle = .long
    return formatter
}

var body: some View {
    NavigationView {
        List {
            ForEach(theperiodlist.periods) {period in
                PeriodRow(period: period)
            }
            .onDelete(perform: removePeriods)
        }
        .navigationBarTitle("Periods")
            .navigationBarItems(trailing:
                Button(action: {self.showingAddPeriod = true}) {
                    Image(systemName: "plus")
                }
            )
        .sheet(isPresented: $showingAddPeriod) {
            AddPeriod(theperiodlist: self.theperiodlist).environmentObject(self.theprofile)
        }
    }
}
func removePeriods(at offsets: IndexSet) {
    AdjustProfileRemove(period: theperiodlist.periods[XXX])
    theperiodlist.periods.remove(atOffsets: offsets)
}

У меня есть отдельная функция (AdjustProfileRemove (period )) которую я хочу вызвать с удаленным периодом в качестве переменной - например, я хочу найти XXX в AdjustProfileRemove (period: theperiodlist.periods [XXX]). Есть ли простой способ сделать это (я полагаю, из IndexSet) или я упускаю что-то фундаментальное?

Спасибо.

Ответы [ 2 ]

1 голос
/ 23 января 2020

Здесь возможен подход (учитывая, что в общем случае offsets может содержать много индексов)

func removePeriods(at offsets: IndexSet) {
    theperiodlist.periods = 
        theperiodlist.periods.enumerated().filter { (i, item) -> Bool in
            let removed = offsets.contains(i)
            if removed {
                AdjustProfileRemove(period: item)
            }
            return !removed
        }.map { $0.1 }
}
1 голос
/ 23 января 2020

.onDelete объявляется как

@inlinable public func onDelete(perform action: ((IndexSet) -> Void)?) -> some DynamicViewContent

IndexSet - это просто набор всех индексов элементов в массиве для удаления. Давайте попробуем этот пример

var arr = ["A", "B", "C", "D", "E"]
let idxs = IndexSet([1, 3])

idxs.forEach { (i) in
    arr.remove(at: i)
}
print(arr)

, поэтому результирующее значение arr теперь равно

["A", "C", "D"]

. Причина, по которой .onDelete использует IndexSet, заключается в том, что для операции удаления можно выбрать более одной строки в списке List. .

БУДЬТЕ ОСТОРОЖНЫ! смотрите полученный массив! На самом деле для удаления элементов один за другим нужно немного логики c ...

Давайте попробуем

var arr = ["A", "B", "C", "D", "E"]
let idxs = IndexSet([1, 3])

idxs.sorted(by: > ).forEach { (i) in
    arr.remove(at: i)
}
print(arr)

это работает сейчас, как вы ожидали, не так ли? результат теперь равен

["A", "C", "E"]

На основании

theperiodlist.periods.remove(atOffsets: offsets)

кажется, что ThePeriodList уже имеет встроенную функцию с необходимой функциональностью.

в вашем случае просто замените

AdjustProfileRemove(period: theperiodlist.periods[XXX])

на

offsets.sorted(by: > ).forEach { (i) in
    AdjustProfileRemove(period: theperiodlist.periods[i])
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...