gpt4 book ai didi

加载数据后 Swift 对象不符合 Equatable

转载 作者:行者123 更新时间:2023-11-30 10:31:51 24 4
gpt4 key购买 nike

从 plist 加载后,我遇到了似乎不符合 Equatable 协议(protocol)的对象的问题。一些背景:我有一个对象 TransmitterList 类型,其中包含 Transmitters 类型的数组。第一次启动时,一切正常,我可以通过调用

来删除项目
if let index = transmitterList.transmitters.firstIndex(of: transmitter) {
transmitterList.transmitters.remove(at: index)
}

此方法在第一次运行时完美运行,问题是在终止应用程序后保存并重新加载应用程序数据后出现的。所有保存和加载都是使用 Codable 协议(protocol)和 Plist 编码器和解码器完成的。 TransmitterList 中的发射器仍然存在,但当尝试删除发射器时,对 firstIndex(of:) 的调用返回 nil。其他依赖 Equatable 协议(protocol)的方法也无法正常运行。似乎保存的发射器不再符合Equatable。但是,重新启动后添加新的发射器时,我能够成功删除任何新添加的发射器。

我能够通过比较一些发射器属性并以这种方式删除它们来创建一个解决方案,但它看起来不是很稳健。真的很想了解发射器不再符合Equatable的根本原因。

感谢任何帮助,谢谢!!

更新了保存和加载代码。

这是我正在使用的 dataModel 对象,它仅保存 TransmitterList 数组。 Transmitter 类中没有自定义编码或解码,它只是符合 Codable 而不需要任何额外的方法。

class DataModel {

// MARK: - Properties
var transmitterLists = [TransmitterList]()

// MARK: - Initialization
init() {
loadData()
}

// MARK: - Data Persistence

func documentsDirectory() -> URL {

let paths = FileManager.default.urls(for: .documentDirectory,
in: .userDomainMask)
return paths[0]
}

func dataFilePath() -> URL {

return documentsDirectory().appendingPathComponent("FrequencyCoordinator.plist")

}

func saveData() {

let encoder = PropertyListEncoder()

do {

let data = try encoder.encode(transmitterLists)

try data.write(to: dataFilePath(), options: Data.WritingOptions.atomic)

print("DATA SAVED!!")
} catch {
print("That did not work: \(error.localizedDescription)")
}

}

func loadData() {

let path = dataFilePath()

if let data = try? Data(contentsOf: path) {

let decoder = PropertyListDecoder()

do {
print("DATA LOADED")


transmitterLists = try decoder.decode([TransmitterList].self, from: data)


} catch {
print("That didnt work ;-< \(error.localizedDescription)")
}
}

}


}

添加 Transmitter 类。任何其他类型也符合 Codable,但只能通过在定义中声明来实现。也许还需要做更多的工作来确保类型正确一致?

class Transmitter: Equatable, Codable {

static func == (lhs: Transmitter, rhs: Transmitter) -> Bool {
return lhs.id == rhs.id
}


var id: Int
var name: String
var transmitterType: TransmitterType
var block: Block
var frequency: Frequency
var doesOverlap: Bool = false
var transmitterOverlapRange: ClosedRange<Double>
var imProductOverlapRanges = [ClosedRange<Double>]()
var overlapsWith = [Transmitter]()
var doesHaveTwoTransmitterIMInterference = false
var doesHaveThreeTransmitterIMInterference = false
var twoTransmitterIMProductsOverlap = [TwoTransmitterIMProduct]()
var threeTransmitterIMProductsOverlap = [ThreeTransmitterIMProduct]()
var isDisabled = false

var frequencyIsSet: Bool {
get {
self.frequency.literal != 0.0
}
}

init(name: String, type: TransmitterType, block: Block, frequency: Frequency, transmitterOverlapRange: ClosedRange<Double>) {
self.id = DataModel.nextTransmitterID()
self.name = name
self.transmitterType = type
self.block = block
self.frequency = frequency
self.transmitterOverlapRange = transmitterOverlapRange

}

enum TransmitterType: Int, Codable {
case talent
case hops
case ifb
}

}

最佳答案

您还没有显示相关代码。你提示的是

if let index = transmitterList.transmitters.firstIndex(of: transmitter)

失败,但您没有显示该行在代码中出现的位置,也没有告诉我们发射器是什么或transmitterList中有什么。

但是,您已经展示了足够的内容,可以进行猜测。您重新定义了发送器的相等性,当且仅当两个发送器的 id 值相等时,它们才相等。

static func == (lhs: Transmitter, rhs: Transmitter) -> Bool {
return lhs.id == rhs.id
}

因此我们可以得出这样的结论:

if let index = transmitterList.transmitters.firstIndex(of: transmitter)

...您的发射器与列表中的任何发射器具有不同的id。如果这是一个新的发射器,这将是有意义的,因为它将使用新的id生成。

事实上,你说过:

I was able to create a work around by comparing some of the transmitters attributes and removing them that way but it doesnt seem very robust

确实没有。但这表明您似乎期望一个发射器根据“其某些属性”与另一个发射器等同。事实并非如此。 唯一的平等点是id。因此,我们可以得出结论,您正在尝试在其他发射器列表中查找具有唯一 id发射器 - 当然它不在那里,因为唯一的id 根据定义,是唯一的。

关于加载数据后 Swift 对象不符合 Equatable,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59009679/

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