SwiftUI 删除 ForEach 子视图中的数组条目

问题描述

我对 IOS 开发还很陌生,所以如果我以完全不正确的方式使用了代码,请多多包涵。

我使用 swiftui 2,我的问题是我的数据结构中有一个数组,其中包含我想通过 ForEach 在另一个视图中显示的信息。到目前为止,这是有效的,但如果我在其中一个子视图中更改数组,则会出现 索引超出范围错误

以下是数据结构示例:

struct Test  {
    var id: String
    var array : Array<String>
}

环境对象

class DBhandler: ObservableObject {
    
    @Published var arrays: Test
    
    init(arrays: Test) {
        self.arrays = arrays
    }
}

应用文件

@main
struct DummyApp: App {
    @Observedobject var dbhandler = DBhandler(arrays: Test(id: "1",array: ["Car","Bus","Train"]))
    
    var body: some Scene {
        WindowGroup {
            ContentView().environmentObject(dbhandler)
        }
    }
}

主视图

struct ContentView: View {
    @EnvironmentObject var dbhandler: DBhandler
    
    var body: some View {

        vstack{
            ForEach(dbhandler.arrays.array.indices,id: \.self) {index in
                SubView(index: index)
            }
        }
        
    }
}

子视图

struct SubView : View {
    @EnvironmentObject var dbhandler: DBhandler
    
    let index: Int
    var body: some View {
        vstack{
            Text(dbhandler.arrays.array[index]) <--- here's the index out of range error
            Button(action: {
                dbhandler.arrays.array.remove(at: index)
            },label: {
                Text("Remove object")
            })
        }

    }
}

我的假设是 ForEach 不是指最新的 dbhandler.arrays.array.indices 而是指旧存储的,但我不知道如何规避它。

你们中有人知道我该如何解决这个问题吗?

非常感谢任何帮助:)

解决方法

对于任何有同样问题的人。我已经想出了如何实现它的方法。由于 ForEach 存储原始数组并且未引用原始数组,因此可能的解决方法是强制 ForEach 自行更新。你可以这样做:

struct ContentView: View {
    @EnvironmentObject var dbhandler: DBhandler
    @State var dummyVar : Int = 0

    var body: some View {

        VStack{
            ForEach(dbhandler.arrays.array.indices,id: \.self) {index in
                SubView(index: index,dummyVar : dummyVar)
            }.id(dummyVar)
        }
        
    }
}

并且在子视图中,您只需要将 dummyVar 增加 1。

,

您可以通过在 SubView index 中添加检查来修复崩溃,如果索引超出范围则不会呈现视图

<?php


use Tests\Helpers\Api\ResponseApi;
use App\Services\ExternalApi\BigBoost\PeopleService;
use App\Services\Repositories\PersonalDataRepository;

uses(ResponseApi::class);

test('should register data in the personal data table with the bigbooster api data ',function () {

$dataApi = $this->responseBigboostPeople();

$placeEmail = \App\Models\PlaceEmail::factory()->make();

$peopleService = mock(PeopleService::class);

$peopleService
    ->expects($this->once())
    ->method('make')
    ->willReturn($dataApi);

$personalDataRepository = new PersonalDataRepository();

$response = $personalDataRepository->create($placeEmail,$peopleService);

$this->assertEquals($placeEmail->email,$response->email);
$this->assertEquals('TESTE DA SILVA',$response->name);
$this->assertEquals('LEAO',$response->zodiac_sign);
$this->assertEquals('Mother user',$response->mother_name);
$this->assertEquals('Father user',$response->father_name);
$this->assertEquals('11111111111',$response->cpf);
$this->assertEquals('1991-08-04',$response->birth_date);
});

enter image description here