Сохранить пользовательскую структуру в плоском файле

Ниже приведена пользовательская структура. Я хотел сохранить массив пользовательских структур [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 возвращает ноль

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

person HMI Platform    schedule 14.04.2020    source источник
comment
пожалуйста, покажите нам свой код, который вы пробовали до сих пор. это не мы пишем код для вас на бесплатной платформе, а мы помогаем вам с вашей существующей кодовой платформой.   -  person Chris    schedule 14.04.2020
comment
@Chris, обновил мой пост   -  person HMI Platform    schedule 14.04.2020


Ответы (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 может быть достигнуто автоматически. Получите imageData из UIImage, используя image.pngData().

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
    }
}
person Jithin    schedule 14.04.2020
comment
Когда я реализую Codable в структуре, такой как детали структуры: Идентифицируемый, Кодируемый {let id = UUID() var name: String? переменное время: строка? var msg : [MsgDetails]? var loc : строка? тип переменной: строка? } Я получаю сообщение об ошибке, например, тип «details» не соответствует протоколу «Decodable» Тип «details» не соответствует протоколу «Encodable» - person HMI Platform; 14.04.2020
comment
Каково содержимое MsgDetails? - person Jithin; 14.04.2020
comment
Если вы хотите использовать NSKeyedArchiver, ваша модель должна быть классом, унаследованным от NSObject, и принять протокол NSCoding и его необходимые методы. Обратитесь к этому ответу: stackoverflow.com/a/51816174/5443937 - person Jithin; 14.04.2020
comment
MsgDetails — это объекты класса msg. class msg { // 2.Свойства var text: String? переменное изображение: UIImage? переменная дата: NSDate? } - person HMI Platform; 14.04.2020
comment
UIImage не соответствует Codable. Вот почему вы получаете эту ошибку. - person Jithin; 14.04.2020