Записать содержимое массива (пользовательского типа) в plist как массив с ключами в swift - PullRequest
0 голосов
/ 12 мая 2019

MacOS, Swift 4.

Я хочу сохранить данные в листе.Я могу загрузить значения, но при их записи они неправильно форматируются.

При этом я загружаю plist (для отображения в виде таблицы), который отлично работает:

    func loadBooks() {
        let path = dataFilePath() // /com.name.books/Data/Documents/

        do {
            let data = try Data(contentsOf: path)
            let decoder = PropertyListDecoder()
            let plist = try decoder.decode([String: [Book]].self, from: data)
            books = plist["BooksData"]!
        } catch {
            print("Error occurred: \(error.localizedDescription)")
        }
    }

Это список, который я загружаю:

<plist version="1.0">
    <dict>
    <key>BooksData</key>
    <array>
        <dict>
            <key>author</key>
            <string>First Author</string>
            <key>title</key>
            <string>First Title</string>     
            <key>lentBy</key>
            <string>Person</string>
        </dict>       
        <dict>
            <key>author</key>
            <string>Second Author</string>  
            <key>title</key>
            <string>Book Title2</string>
            <key>lentBy</key>
            <string>Another Person</string>
        </dict>
    </array>  
    </dict>
</plist>

Я пытаюсь записать массив обратно в список следующим образом:

  func saveBooks() {
        let data = books

        do {
            let encoder = PropertyListEncoder()
            var plist = try encoder.encode(data)
            try plist.write(to: dataFilePath())
        } catch {
            print("Error occured: \(error.localizedDescription)")
        }
    }

Содержимое списка теряет свой"wrapping" и ключ ("BooksData") и впоследствии не могут быть прочитаны с помощью функции loadBooks ().

Это вывод:

<plist version="1.0">
    <array>    
        <dict>
            <key>author</key>
            <string>First Author</string>
            <key>title</key>
            <string>First Title</string>     
            <key>lentBy</key>
            <string>Person</string>
        </dict>       
        <dict>
            <key>author</key>
            <string>Second Author</string>  
            <key>title</key>
            <string>Book Title2</string>
            <key>lentBy</key>
            <string>Another Person</string>
        </dict>  
    </array>
</plist>

Я играл с NSMutableDictionary(), пытаясь обернуть его с dict.setObject(plist, forKey: "BooksData") и записав его с dict.write(toFile: dataFilePath().absoluteString, atomically: true).

            let encoder = PropertyListEncoder()
            var plist = try encoder.encode(data)

            dict.setObject(plist, forKey: "BooksData" as NSCopying)
            dict.write(toFile: dataFilePath().absoluteString, atomically: true)
            print(dict)

при печати dict возвращается

{
    BooksData = <62706c69 73743030 a401080c 10d30203 04050607 55746974 6c655661 7574686f 72566c65 6e744279 59427563 68746974 656c5b46 696e6b2c 20457567 656e546e 6f6e65d3 02030409 0a0b5f10 14457266 61687275 6e672075 6e642055 72746569 6c5f100f 48757373 65726c2c 2045646d 756e645a 50617472 69636b20 5379d302 03040d0e 0f5f101a 4b726974 696b2064 65722072 65696e65 6e205665 726e756e 66745e4b 616e742c 20496d6d 616e7565 6c50d302 03041112 0f5b4369 74612041 63746976 615e4172 656e6474 2c204861 6e6e6168 080d141a 2128323e 434a6173 7e85a2b1 b2b9c500 00000000 00010100 00000000 00001300 00000000 00000000 00000000 0000d4>;
}

И файл даже не записывается, то есть старый файл в dataFilePath () остается прежним.

Может ли ответ лежать в PropertyListSerialization.propertyList(from:options:format:)?Или CodingKeys?Или encode(title, forKey:"BooksData") (?) И т. Д.?NSMutableArray?KeyedDecodingContainer, unkeyedContainer и т. Д.?NSKeyedArchiver?

Это кажется такой простой задачей, но я просто не могу понять ее правильно.Вокруг этого, похоже, есть некоторые связанные темы, но на самом деле ничего не применимо и не дало мне важную информацию, чтобы это исправить.Документация также ничего не объясняет для меня, мне нужны конкретные указатели.

Пожалуйста, помогите.

1 Ответ

0 голосов
/ 12 мая 2019

Поскольку ожидаемый тип - [String: [Book]], вам нужно создать корневой словарь вручную

func saveBooks() {
    do {
        let encoder = PropertyListEncoder()
        let plistData = try encoder.encode(["BooksData":books])
        try plistData.write(to: dataFilePath())
    } catch {
        print("Error occured:", error) // never ever print `localizedDescription`
    }
}

Но если plist содержит только массив массива books и сохраняет только массив. Далее рекомендую передать возможную ошибку звонящему

var books = [Book]()

func loadBooks() throws {
    let path = dataFilePath() // /com.name.books/Data/Documents/
    let data = try Data(contentsOf: path)
    let decoder = PropertyListDecoder()
    books = try decoder.decode([Book].self, from: data)
}

Тогда метод сохранения соответствует типу

func saveBooks() throws {
    let encoder = PropertyListEncoder()
    let plistData = try encoder.encode(books)
    try plistData.write(to: dataFilePath())
}
...