将自定义结构保存在平面文件中



下面是自定义结构。我想存储自定义结构的数组,即[详细信息]。无法在文件中存储[详细信息]。在文件中写入此[详细信息]时,应用程序正在崩溃"无效json格式">

struct details : Identifiable {
let id  = UUID()
var name : String?
var time : String?
var msg : [MsgDetails]?
var loc : String?
var type : String?
}

在文件中写入:msgArray是详细信息的数组。msgArray=[详细信息]。

extension Array {
var jsonStringRepresentation: String? {
let jsonData = try? JSONSerialization.data(withJSONObject: self, options: [])
guard jsonData != nil else {return nil}
let jsonString = String(data: jsonData!, encoding: .utf8)
guard jsonString != nil else {return nil}
return jsonString! as String
}
}

在以下代码中,NSKeyedArchiver.archivedData返回零

if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first{
let fileURL = dir.appendingPathComponent(self.fileName)
let data = try? NSKeyedArchiver.archivedData(withRootObject: msgArray.jsonStringRepresentation!, requiringSecureCoding: true)
do {
try data!.write(to: fileURL)
} catch let error {
print("(error.localizedDescription)")
}
}

您可以使用Codable而不是NSKeyedArchiver将模型转换为数据并写入文件。假设您的模型只包含基本类型,那么您所要做的就是遵守Codable协议。

struct Details : Identifiable, Codable {
...
}

写入文件:

extension Array where Element: Encodable {
func saveToFile(fileName: String) throws {
do {
let data = try JSONEncoder().encode(self)
if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let fileURL = dir.appendingPathComponent(fileName)
try data.write(to: fileURL)
} else {
//throw some error
}
} catch {
throw error
}
}
}

保存的文件可以这样读取:

func readFile(fileName: String) throws {
do {
if let dir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
let url = dir.appendingPathComponent(fileName)
let data = try Data(contentsOf: url)
let decoded = try JSONDecoder().decode([Details].self, from: data)
print("decoded: ", decoded)
} else {
//throw some error
}
} catch {
throw error
}
}

如果您可以将模型中的UIImage替换为Data,则可以自动实现Codable一致性。使用image.pngData()UIImage获取imageData。

struct MsgDetails: Codable {
var imageData: Data?
var text: String?
var date: Date?
var image: UIImage? {
if let data = imageData {
return UIImage(data: data)
}
return nil
}
}

相关内容

最新更新