【发布时间】:2019-11-23 16:21:12
【问题描述】:
从 plist 加载后,我遇到的对象似乎不符合 Equatable 协议的问题。一些背景知识:我有一个对象 TransmitterList 类型,它包含一个 Transmitters 类型的数组。在第一次启动时,一切正常,我可以通过调用删除项目
if let index = transmitterList.transmitters.firstIndex(of: transmitter) {
transmitterList.transmitters.remove(at: index)
}
此方法在第一次运行时完美运行,问题出现在应用程序数据已保存并在终止应用程序后重新加载后。所有保存和加载都是使用Codable 协议和 Plist 编码器和解码器完成的。发射器列表中的发射器仍然存在,但在尝试删除发射器时,对firstIndex(of:) 的调用返回nil。其他依赖Equatable 协议的方法也无法正常运行。似乎已保存的发射器不再符合Equatable。但是,在重新启动后添加新发射器时,我能够成功删除任何新添加的发射器。
我能够通过比较一些发射器属性并以这种方式删除它们来创建一个解决方法,但它似乎不是很强大。真的想了解发射机不再符合Equatable 的根本原因。
感谢您的帮助,谢谢!
更新了保存和加载代码。
这是我正在使用的 dataModel 对象,它只是保存了一个 TransmitterLists 数组。 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
}
}
【问题讨论】:
-
“真的很想了解发射机不再符合 Equatable 的根本原因。”它们确实符合 Equatable。但是根据您对此对象类型的 Equatable 定义,它们不再相等。
-
我想你是对的。虽然我不完全确定在保存数据和重新加载数据之间发生了什么变化。这个问题也对应用程序的其他部分造成了严重破坏。已保存和加载的发射机似乎不再能够更改其频率。所有标签都会根据新频率进行相应更新,但打印声明在幕后显示发射器的频率实际上并未改变。这些问题只有在保存和加载后才会出现。
-
您是否对发射器对象使用自定义方法
.init(decoder:)和encode(encoder:)?如果是这样,您可以发布它们,因为我怀疑您的解码方式与编码方式不同。 -
@flanker 使用保存和加载方法更新了原始问题。
-
相关的不是加载/保存方法,而是 TransmitterList(和任何子类型)的编码/解码方式。 IE。如何使它们符合 Codable。您可以将 Transmitter 类添加到问题中吗?
标签: swift save loading plist equatable