Ios 符合SwiftUI中RandomAccessCollection时下标索引超出范围
我创建了一个类,并将其确认为Ios 符合SwiftUI中RandomAccessCollection时下标索引超出范围,ios,arrays,swift,swiftui,Ios,Arrays,Swift,Swiftui,我创建了一个类,并将其确认为observeObject以及RandomAccessCollection将该类视为数组的自定义实现,但我不需要它是一个结构。我需要它成为一门课 我试图通过调用名为append的自定义函数将一个项添加到类的内容中,这很好,但是当我要删除时,由于某种原因,它在subscript处崩溃,我试图跟踪它,似乎每次我删除它时,它都会循环通过包括已删除项在内的所有内容,然后崩溃。所以我不确定到底发生了什么。这是一段代码,带有可复制的代码(只需复制并粘贴即可) 如果我将代码更改为s
observeObject
以及RandomAccessCollection
将该类视为数组的自定义实现,但我不需要它是一个结构。我需要它成为一门课
我试图通过调用名为append
的自定义函数将一个项添加到类的内容中,这很好,但是当我要删除时,由于某种原因,它在subscript
处崩溃,我试图跟踪它,似乎每次我删除它时,它都会循环通过包括已删除项在内的所有内容,然后崩溃。所以我不确定到底发生了什么。这是一段代码,带有可复制的代码(只需复制并粘贴即可)
如果我将代码更改为struct,它将100%正常工作,但我需要它作为一个类
测试。swift
import Foundation
public class Test<Element : Hashable>: ObservableObject{
@Published fileprivate var contents:[Element] = []
public var count:Int {
return self.contents.count
}
init() {
}
}
public extension Test {
func append(_ newElement: Element) {
self.contents.append(newElement)
}
func remove(_ at: Int) {
self.contents.remove(at: at)
}
}
extension Test : Collection, RandomAccessCollection {
public typealias Index = Int
public typealias Indices = CountableRange<Int>
public var startIndex: Int {
return self.contents.startIndex
}
public var endIndex: Int {
return self.contents.endIndex
}
public subscript(position: Int) -> Element {
get {
return self.contents[position] // Crash occurs here after trying to remove
}
}
public func index(after i: Int) -> Int {
return self.contents.index(after: i)
}
public func index(before i: Int) -> Int {
return self.contents.index(before: i)
}
}
import SwiftUI
struct ContentView: View {
@ObservedObject var test: Test<String> = Test<String>()
@State var input: String = ""
var body: some View {
VStack {
HStack {
TextField("New Item", text: self.$input)
Button("Add", action: {
if(!self.input.isEmpty) {
self.test.append(self.input)
}
})
}
Button("Remove", action: {
self.test.remove(0)
}).disabled(self.test.count <= 0)
List {
ForEach(self.test, id:\.self) { n in
Text(n)
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
<代码>导入基础
公共类测试:ObservieObject{
@已发布的fileprivate变量内容:[Element]=[]
公共变量计数:Int{
返回self.contents.count
}
init(){
}
}
公共扩展测试{
func append(uElement:Element){
self.contents.append(新元素)
}
func remove(u:Int){
self.contents.remove(at:at)
}
}
扩展测试:集合,随机访问集合{
公共类型别名索引=Int
公共类型别名索引=可数范围
公共变量startIndex:Int{
返回self.contents.startIndex
}
公共变量endIndex:Int{
返回self.contents.endIndex
}
公共下标(位置:Int)->元素{
得到{
return self.contents[position]//尝试删除后此处发生崩溃
}
}
公共函数索引(在i:Int之后)->Int{
返回self.contents.index(在:i之后)
}
公共函数索引(在i:Int之前)->Int{
返回self.contents.index(在:i之前)
}
}
ContentView.swift
import Foundation
public class Test<Element : Hashable>: ObservableObject{
@Published fileprivate var contents:[Element] = []
public var count:Int {
return self.contents.count
}
init() {
}
}
public extension Test {
func append(_ newElement: Element) {
self.contents.append(newElement)
}
func remove(_ at: Int) {
self.contents.remove(at: at)
}
}
extension Test : Collection, RandomAccessCollection {
public typealias Index = Int
public typealias Indices = CountableRange<Int>
public var startIndex: Int {
return self.contents.startIndex
}
public var endIndex: Int {
return self.contents.endIndex
}
public subscript(position: Int) -> Element {
get {
return self.contents[position] // Crash occurs here after trying to remove
}
}
public func index(after i: Int) -> Int {
return self.contents.index(after: i)
}
public func index(before i: Int) -> Int {
return self.contents.index(before: i)
}
}
import SwiftUI
struct ContentView: View {
@ObservedObject var test: Test<String> = Test<String>()
@State var input: String = ""
var body: some View {
VStack {
HStack {
TextField("New Item", text: self.$input)
Button("Add", action: {
if(!self.input.isEmpty) {
self.test.append(self.input)
}
})
}
Button("Remove", action: {
self.test.remove(0)
}).disabled(self.test.count <= 0)
List {
ForEach(self.test, id:\.self) { n in
Text(n)
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
导入快捷界面
结构ContentView:View{
@ObservedObject变量测试:测试=测试()
@状态变量输入:String=“”
var body:一些观点{
VStack{
HStack{
文本字段(“新项目”,文本:self.$input)
按钮(“添加”,操作:{
如果(!self.input.isEmpty){
self.test.append(self.input)
}
})
}
按钮(“移除”),操作:{
自测试。删除(0)
}).disabled(self.test.countForEach
未看到数据中的更改,因为self.test
是一个参考
这里是可能的解决方法(仍然有测试的内容
private)
List {
ForEach(Array(self.test), id:\.self) { n in
Text(n)
}
}
由于超出了数组边界,因此可以将集合的返回值设置为可选值,也可以在init中指定一个默认值,以便在数组为空时返回
@ObservedObject var test: Test<String> = Test<String>(emptyValue: "")
public class Test<Element : Hashable>: ObservableObject{
private let empty: Element
@Published fileprivate var contents:[Element] = []
public var count:Int {
return self.contents.count
}
init(emptyValue: Element) {
empty = emptyValue
}
}
extension Test {
func append(_ newElement: Element) {
self.contents.append(newElement)
}
func remove(_ at: Int) {
self.contents.remove(at: at)
}
}
extension Test : Collection, RandomAccessCollection {
public typealias Index = Int
public typealias Indices = CountableRange<Int>
public var startIndex: Int {
return self.contents.startIndex
}
public var endIndex: Int {
return self.contents.endIndex
}
public subscript(position: Int) -> Element {
get {
position < self.contents.count ? self.contents[position] : empty
}
}
public func index(after i: Int) -> Int {
return self.contents.index(after: i)
}
public func index(before i: Int) -> Int {
return self.contents.index(before: i)
}
}
@ObservedObject变量测试:测试=测试(emptyValue:)
公共类测试:ObservieObject{
私有let空:元素
@已发布的fileprivate变量内容:[Element]=[]
公共变量计数:Int{
返回self.contents.count
}
init(emptyValue:Element){
empty=emptyValue
}
}
延伸试验{
func append(uElement:Element){
self.contents.append(新元素)
}
func remove(u:Int){
self.contents.remove(at:at)
}
}
扩展测试:集合,随机访问集合{
公共类型别名索引=Int
公共类型别名索引=可数范围
公共变量startIndex:Int{
返回self.contents.startIndex
}
公共变量endIndex:Int{
返回self.contents.endIndex
}
公共下标(位置:Int)->元素{
得到{
位置Int{
返回self.contents.index(在:i之后)
}
公共函数索引(在i:Int之前)->Int{
返回self.contents.index(在:i之前)
}
}
我可以看到列表随着代码的添加而改变,也没有变化;但是,即使在您提议的更改之后,当我尝试删除时,索引仍然超出范围。
感谢您的回复。这确实解决了问题,但我理解这是一个解决方法。我还理解,ForEach
在g更改,但我无法理解的是,为什么在我执行添加
而不是删除
时,它能够看到更改?您是否认为在此时没有黑客攻击就无法做到这一点?或者我现在要求的对类来说是不可能的?因为上面的代码对struct
但我知道struct是值类型。谢谢您的帮助。