在 BehaviourRelay 中更新嵌套属性的最佳方法

问题描述

我有以下型号

final class Vehicle {
var cars:[SportsCar] = []
}

final class SportsCar {
var isCheap:Bool = false
}

假设 Vehicle 和 SportsCar 都是 Equatable(为了简单起见,我省略了 Equatable 一致性)。

目标:更新嵌入在 Vehicles BehaviorRelay 中继内的汽车数组中的一辆车的 isCheap 属性

尝试:

final class viewmodel {
    let vehicles:BehaviorRelay<[Vehicle]> = BehaviorRelay(value: [])
    // Attempt 1: Access vehicles direct without making a copy.
    
    // Toggling `isCheap` property when user tap a button on a collectionView cell.
    func updateCarProperty(checkedVehicle:Vehicle,checkedindexPath:IndexPath){
        for car in vehicles.value[checkedindexPath.section].cars {
            let checkedCar = checkedVehicle.cars[checkedindexPath.item]
            if car == checkedCar {
                if car.isCheap {
                    vehicles.value[checkedindexPath.section].cars[checkedindexPath.item].isCheap = false
                }else {
                    vehicles.value[checkedindexPath.section].districts[checkedindexPath.item].isCheap = true
                }
                break
            }
        }
    }
    
}


// Attempt 2: Make a copy of vehicles then use it to change the property then on completion update the whole vehicles array by calling
//vehicles.accept(vehiclescopy)
// As described on this answer: https://stackoverflow.com/a/58295908/7551807
// This approach didn't work too.

期望: Car isCheap 属性函数调用完成后发生变化。

结果:属性没有按预期改变?。无论如何它只是保持认值(false)!

问题:还有其他更好的方法来处理这个问题吗?

解决方法

您必须创建对象的全新副本并将其发送到中继。您不能发出“子集”或中继的类型,因为它发出 [Vehicle] 类型的值,因此您必须始终向其发送新的车辆数组。

您必须创建一个车辆数组的副本,改变所需的项目,然后使用 .accept(updatedVehicles) 将整个数组发回。