【问题标题】:Save custom struct in Flat file将自定义结构保存在平面文件中
【发布时间】:2020-04-14 05:24:16
【问题描述】:

以下是自定义结构。我想存储 [details] 的自定义结构数组。我无法将 [详细信息] 存储在文件中。在写这个[文件中的细节,应用程序崩溃'无效的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 返回 nil

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)")
            }
        }

【问题讨论】:

  • 请向我们展示您迄今为止尝试过的代码。这不是一个“我们免费为您编写代码”的平台,而是一个“我们帮助您编写现有代码”的平台。
  • @Chris,更新了我的帖子

标签: ios swift swift5.2


【解决方案1】:

您可以使用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
    }
}

【讨论】:

  • 当我在 struct 中实现 Codable 时,比如 struct details : Identifiable, Codable { let id = UUID() var name : String?变量时间:字符串? var msg : [MsgDetails]? var loc : 字符串?变量类型:字符串?出现错误,例如 Type 'details' does not conform to protocol 'Decodable' Type 'details' does not conform to protocol 'Encodable'
  • MsgDetails的内容是什么?
  • 如果你想使用 NSKeyedArchiver,你的模型必须是继承自 NSObject 的类,并采用 NSCoding 协议和它的必需方法。参考这个答案:stackoverflow.com/a/51816174/5443937
  • MsgDetails 是 msg 类的对象。 class msg { // 2.Properties var text: String?变种图像:UIImage?变量日期:NSDate? }
  • UIImage 不符合 Codable。这就是您收到该错误的原因。
猜你喜欢
  • 1970-01-01
  • 2015-12-04
  • 2017-04-25
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多