致命错误:在特定视图上刷新数据时索引超出范围
Posted
技术标签:
【中文标题】致命错误:在特定视图上刷新数据时索引超出范围【英文标题】:Fatal error: Index out of range when refreshing data on specific view 【发布时间】:2020-07-30 12:24:08 【问题描述】:我有以下代码:
import SwiftUI
import SwiftUIRefresh // added via SwiftPM: https://github.com/timbersoftware/SwiftUIRefresh.git
struct AView: View
@State private var aObjects = [A]()
@State private var refreshing = false
var body: some View
NavigationView
VStack
if(aObjects.isEmpty)
Text("loading")
else
List(aObjects.indices, id: \.self) idx in
NavigationLink(destination: BView(parentA: self.$aObjects[idx]))
Text(self.aObjects[idx].name)
.pullToRefresh(isShowing: self.$refreshing)
API.getAs() newAObjects in
self.aObjects = newAObjects
self.refreshing = false
.navigationBarTitle("All", displayMode: .large)
.onAppear()
if(self.aObjects.isEmpty)
API.getAs() newAObjects in
self.aObjects = newAObjects
struct BView: View
@Binding var parentA : A
@State private var refreshing = false
var body: some View
VStack
if(parentA.bs.isEmpty)
Text("loading")
else
List(parentA.bs.indices, id: \.self) idx in
NavigationLink(destination: CView(parentA: self.$parentA, parentB: self.$parentA.bs[idx]))
Text(self.parentA.bs[idx].name)
.pullToRefresh(isShowing: self.$refreshing)
API.getBs(forA: self.parentA) newBObjects in
self.parentA.bs = newBObjects
self.refreshing = false
.navigationBarTitle(Text(parentA.name), displayMode: .inline)
.onAppear()
if(self.parentA.bs.isEmpty)
API.getBs(forA: self.parentA) newBObjects in
self.parentA.bs = newBObjects
struct CView: View
@Binding var parentA : A
@Binding var parentB : B
@State private var refreshing = false
var body: some View
VStack
if(parentB.cs.isEmpty)
Text("loading")
else
List(parentB.cs.indices, id: \.self) idx in
Text(self.parentB.cs[idx].name + self.parentB.cs[idx].description)
.pullToRefresh(isShowing: self.$refreshing)
API.getCs(forB: self.parentB, inA: self.parentA) newCObjects in
self.parentB.cs = newCObjects
self.refreshing = false
.navigationBarTitle(Text(parentB.name), displayMode: .inline)
.onAppear()
if(self.parentB.cs.isEmpty)
API.getCs(forB: self.parentB, inA: self.parentA) newCObjects in
self.parentB.cs = newCObjects
class API
static func getAs(complete : @escaping ([A]) -> Void)
// normaly download from server
let aobjects = [A(id: 1, name: "1"), A(id: 2, name: "2"), A(id: 3, name: "3")]
complete(aobjects)
static func getBs(forA : A, complete: @escaping ([B]) -> Void)
// normaly download all bs for a provided A from server
let bObjects = [B(id: 4, name: "4"), B(id: 5, name: "5")]
complete(bObjects)
static func getCs(forB : B, inA: A, complete: @escaping ([C]) -> Void)
// normaly download all cs for a provided B in parent A from server
let cObjects = [C(id: 6, name: "name", description: "desc")]
complete(cObjects)
struct A
public let id : Int
public let name : String
public var bs = [B]()
init(id: Int, name: String)
self.id = id
self.name = name
struct B
public let id : Int
public let name : String
public var cs = [C]()
init(id: Int, name: String)
self.id = id
self.name = name
struct C
public let id : Int
public let name : String
public let description : String
init(id: Int, name: String, description : String)
self.id = id
self.name = name
self.description = description
到目前为止,这有效。用户可以从 AView 导航到 BView 再到 CView。如果用户执行以下操作,则会出现标题中的问题和错误:从 AView 开始,转到 BView,转到 CView,返回 BView,返回 AView,通过下拉手势刷新。在其他情况下,它不会发生,例如。从 AView 开始,转到 BView,转到 CView,返回 BView,返回 AView,转到另一个 BView,返回 AView, 通过下拉手势刷新,这样可以。知道如何防止异常吗?
提前致谢
编辑:完整的错误消息
致命错误:索引超出范围:文件 /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1103.2.25.8/swift/stdlib/public/core/ContiguousArrayBuffer.swift,第 444 行 2020-07-30 14:16:37.652919+0200 TestForArray[11908:625819] 致命错误:索引超出范围:文件 /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-1103.2.25.8/swift/ stdlib/public/core/ContiguousArrayBuffer.swift,第 444 行
【问题讨论】:
它是在“正常”条件下(新数据到达时)失败,还是在固定刷新数据时也失败,就像问题中一样 【参考方案1】:您试图从超出数组范围的索引中获取数据。您可以使用此扩展程序。它将帮助您安全地获取对象。 https://github.com/MahmoudMMB/MahmoudMMB-Fetching_an_item_from_array_safely/blob/main/SafeFetching.swift
【讨论】:
不允许仅链接答案。链接会随着时间而中断。如果链接中有相关代码,请将代码贴在答案中 您应该观看 WWDC21 中的 Demystify SwiftUI,因此 Apple 认为这种特定做法是不安全的,应该避免 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于致命错误:在特定视图上刷新数据时索引超出范围的主要内容,如果未能解决你的问题,请参考以下文章
CollectionView - 致命错误:索引超出范围 - 比视图显示的单元格多
使用致命错误刷新tableview时应用程序崩溃:索引超出范围Swift3