gpt4 book ai didi

ios - 如何在 SwiftUI (iOS) 中处理数据删除而不导致应用程序崩溃

转载 作者:行者123 更新时间:2023-11-29 05:17:04 25 4
gpt4 key购买 nike

我有一个 SwiftUI 日历应用程序,其 UI 类似于内置 Calendar.app。每当我尝试删除事件时,都会发生崩溃。我的应用程序的整体生命周期如下:

  • 从服务器下载日历数据并填充模型([事件]、[用户]、[响应] 等)
  • 将源数据转换为更结构化的格式(请参阅 https://stackoverflow.com/a/58583601/2282313)
  • 呈现事件 ListView ,每个事件都链接到详细信息 View 和编辑模式(与 calendar.app 非常相似)
  • 删除事件时,我告诉服务器删除该事件(如果是重复事件,服务器将删除多个事件),然后通过重新下载数据、重新填充数据来刷新服务器中的数据模型并重新生成结构化数据(这会导致列表刷新)。

当我这样做时,我的计算值导致崩溃,因为详细 View 中显示的事件数据不再可用。例如,我获取用户RSVP的数组索引如下:

    var responseIndex: Int {
userData.responses.firstIndex(where: { $0.user == response.user && $0.occurrence == response.occurrence })!
}

我认为这是因为我在更新数据之前没有关闭显示已删除事件的 View ,但即使我延迟数据刷新直到 View 不再显示,我仍然会崩溃(SwiftUI 似乎保留这些 View 在内存中)。

处理数据删除的正确方法是什么?我是否需要将已删除的事件保留在我的 UserData EnvironmentObject 中并将它们标记为“已删除/隐藏”以避免此问题,或者是否有更好的方法来处理它?<​​/p>

这涉及相当多的代码,因此提供示例很棘手,如果有人要求,我很乐意添加相关位。

最佳答案

编辑:我发现这篇文章很好地澄清了一些事情:https://jasonzurita.com/swiftui-if-statement/

SwiftUI 非常乐意尝试渲染 nil View ,它只是不绘制任何内容。与直觉相反,避免崩溃并使编译器满意的一个好方法是围绕此设置代码。

原始“答案”如下...

我不知道这是否是“正确”的方法,但我最终确保我的任何 UserData 都不会被删除以避免崩溃。我向我的 Occurrence(即事件)对象添加了一个“已删除” bool 值,当我刷新结构化数据时,我从服务器获取最新数据,但检查是否有任何旧数据不再存在。步骤是:

  1. 从服务器获取最新的事件列表
  2. 为我的结构化数据创建第二个 init(),它将现有数据作为参数
  3. 在新的 init() 中,展平结构化数据,根据新数据检查已删除的项目,更新尚未删除的数据,剔除重复项,然后合并到净新数据中。完成后,我使用修改后的数据调用原始 init() 以创建新的结构化数据

代码如下所示:

init(occurrences: [Occurrence], existing: [Day]) {

// Create a mutable copy of occurrences (useful so I can delete duplicates)
var occurrences = occurrences

// Flatten the structured data into a plan array of occurrences again
var existingOccurrences = existing.compactMap({ $0.occurrences }).flatMap { $0 }

// Go through existing occurrences and see if they still exist.
existingOccurrences = existingOccurrences.map {
occurrence -> Occurrence in
let occurrenceIndex: Int? = occurrences.firstIndex(where: { $0.id == occurrence.id })
// If the occurrence no longer exists, mark it as "deleted" in the original data
if occurrenceIndex == nil {
var newOccurrence = occurrence
newOccurrence.deleted = true
return newOccurrence
// If it still exists, replace the existing copy with the new copy
// (in case it has changed since the last pull from the server)
// Remove the event from the "new" data so you don't get duplicates
} else {
let newOccurrence = occurrences[occurrenceIndex!]
occurrences.remove(at: occurrenceIndex!)
return newOccurrence
}
}

// Merge the existing data (with deleted items marked) and the updated data (with deleted items removed)
let finalOccurrences = existingOccurrences + occurrences

// Re-initialize the strutured data with the new array of data
self = EventData(occurrences: finalOccurrences)
}

完成此操作后,我必须更新我的代码,以确保我始终使用我的结构化数据作为事实来源(我之前没有这样做,因为访问“源” “平面数据通常更容易,并且我已在 ListView 中更新了 ForEach,以便仅在删除为 false 时才渲染行。

它有效!这可能是解决问题的次优方法,但不会再出现崩溃。仍然有兴趣听到解决问题的更好方法。

关于ios - 如何在 SwiftUI (iOS) 中处理数据删除而不导致应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59079874/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com