Сохранять привязку при перемещении элемента из одного массива в другой?IOS

Программируем под IOS
Ответить
Anonymous
 Сохранять привязку при перемещении элемента из одного массива в другой?

Сообщение Anonymous »

У меня есть приложение, в котором пользователь может создавать мероприятия для городов. Пользователь может выбрать дату и время для каждого события.
На странице города пользователь может увидеть все его события, а также установить дату и время. каждого события. Страница города разделена на два раздела: неорганизованные мероприятия и организованные мероприятия. Неорганизованные события — это просто события без указания даты.
Поэтому, когда пользователь переходит на страницу города, мой API возвращает два массива: массив неорганизованных событий и массив организованных событий.< /p>
Когда пользователь устанавливает дату неорганизованного мероприятия, он перемещает событие в массив организованных событий.
Кроме того, на странице города отображается пользователь может создать новое событие, которое автоматически добавляется в массив неорганизованных событий.
Однако у меня возникает сбой, который происходит, когда:
  • Пользователь создает новое событие.
  • Пользователь нажимает на это новое событие.
  • Устанавливает дату (которая добавляет его). в массив организованных событий)
  • Устанавливает время (здесь происходит сбой)
Ошибка:

Тема 1. Неустранимая ошибка: индекс выходит за пределы диапазона

Я думаю, что это могло быть связано с тем фактом, что привязка не поддерживается и не может найти событие после его перемещения из массива неорганизованных событий в массив организованных событий.
Вот мой код . Я опустил некоторые несущественные моменты.
Класс MyApp, который действует как единственный источник истины:
@main
struct MyApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate

@StateObject var cityManager = CityManager(cityService: CityService())

var body: some Scene {
WindowGroup {
NavigationView {
MainView()
.environmentObject(cityManager)
}
}
}
}

HomeView, где я показываю список городов:
struct HomeView: View {

@StateObject private var vm = HomeViewModel(homeService: HomeService())

@Binding var tabSelection: Int

@EnvironmentObject var cityManager: CityManager

var body: some View {
NavigationStack {
ScrollView(showsIndicators: false) {
VStack(spacing: 0) {
ScrollView(.horizontal, showsIndicators: false) {
HStack(alignment: .top, spacing: 32) {
ForEach($cityManager.cities, id: \.id) { $city in
CityItem(city: $city, axes: .horizontal)
}
}
}
}
}
}
.onAppear {
vm.fetchHome()
}
.onChange(of: vm.cities?.count) {
cityManager.cities = vm.cities ?? []
}
.environmentObject(cityManager)
}
}

CityItem:
struct StadiumItem: View {
@Binding var city: City

var body: some View {
NavigationLink(destination: CityPageView(city: $city)) {
VStack {
Text(city.name)
}
}
}
}

CityPageView — главная страница, на которой показаны все события, происходящие в городе:
struct CityPageView: View {
@Binding var city: City

@EnvironmentObject var cityManager: CityManager
@StateObject var cityPageViewModel = CityPageViewModel()

var body: some View {
NavigationView {
ZStack(alignment: .top) {
ScrollViewReader { value in
ScrollView(showsIndicators: false) {
VStack(spacing: 0) {
// List of unorganized events
UnorganizedEventsView(city: $city)

// List of organized events
OrganizedEventsView(days: $city.organizedEvents)
}
}
}
}
}
.environmentObject(cityManager)
.environmentObject(cityPageViewModel)
}
}

struct UnorganizedEventsView: View {
@Binding var city: City

var body: some View {
let unorganizedEvents = $city.unorganizedEvents
if (!unorganizedEvents.isEmpty) {
VStack(alignment: .leading, spacing: 0) {
Text("Unorganized")

LazyVStack(spacing: 0) {
ForEach(unorganizedEvents, id: \.id) { $event in
EventView(
event: $event,
isLast: event == unorganizedEvents.wrappedValue.last
)
}
}
}
.id("Unorganized")
}
}
}

struct OrganizedEventsView: View {
@Binding var days: [Day]

var body: some View {
ForEach($days, id: \.id) { $day in
VStack(alignment: .leading, spacing: 0) {
Text(day.date.toDayDate() ?? "")

LazyVStack {
ListEventsView(events: $day.events)
}
}
.id(day.date)
}
}
}

Вот мой класс модели города:
struct City: Codable, Identifiable {
var id: Int
var name: String
var events: [Event]? {
didSet {
self.unorganizedEvents = self.getUnorganizedEvents()
self.organizedEvents = self.getOrganizedEvents()
}
}
var unorganizedEvents: [Event] = []
var organizedEvents: [Day] = []

enum CodingKeys: String, CodingKey {
case id = "id"
case name = "name"
case events = "events"
}

init(id: Int, name: String, events: [Event] = [], unorganizedEvents: [Event] = []) {
self.id = id
self.name = name
self.events = events
self.unorganizedEvents = unorganizedEvents
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(Int.self, forKey: .id)
self.name = try container.decode(String.self, forKey: .name)
self.events = try container.decodeIfPresent([Event].self, forKey: .events) ?? []
self.unorganizedEvents = self.getUnorganizedEvents()
self.organizedEvents = self.getOrganizedEvents()
}

func getUnorganizedEvents() -> [Event] {
return events?.filter({ $0.date == nil }) ?? []
}

func getOrganizedEvents() -> [Day] {
guard let events = events else {
return []
}

var eventsByDay: [String: [Event]] = [:] // Dictionary to store events grouped by date

// Group events by date
for event in events {
if let date = event.date {
if var eventsOnDate = eventsByDay[date] {
eventsOnDate.append(event)
eventsByDay[date] = eventsOnDate
} else {
eventsByDay[date] = [event]
}
}
}

// Create Day instances for each group of events
var days: [Day] = []
for (date, events) in eventsByDay {
let sortedEvents = events.sorted { ($0.timeStart ?? "24:59:59") < ($1.timeStart ?? "24:59:59") }
let day = Day(date: date, events: sortedEvents)
days.append(day)
}

days.sort { $0.date < $1.date }

return days
}
}

Что я делаю неправильно, что может привести к сбою?

Изменить< /p>
Основываясь на комментариях, я решил использовать только один массив. Однако я изо всех сил пытаюсь фильтровать события, сохраняя при этом обновление отфильтрованного массива при обновлении исходного city.events.
struct CityListView: View {
@Binding var city: City

var body: some View {
VStack(alignment: .leading, spacing: 0) {
LazyVStack(spacing: 0) {

// Here, I want to filter by events where date = nil
ForEach($city.events, id: \.id) { $event in
EventView(
event: $event
)
}
}
}
}
}

Вот модель моего города:
struct City: Codable, Identifiable {
var id: Int
var name: String
var events: [Event] = []

enum CodingKeys: String, CodingKey {
case id = "id"
case name = "name"
case events = "events"
}

init(id: Int, name: String, events: [Event] = []) {
self.id = id
self.name = name
self.events = events
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(Int.self, forKey: .id)
self.name = try container.decode(String.self, forKey: .name)
self.events = try container.decodeIfPresent([Event].self, forKey: .events) ?? []
}
}


Подробнее здесь: https://stackoverflow.com/questions/790 ... to-another
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»