NSUserDefaultsController: «Попытка установить объект списка не-свойств ... как значение NSUserDefaults / CFPreferences для ключа ...» - PullRequest
0 голосов
/ 26 января 2019

Я пытаюсь использовать NSUserDefaultsController для реализации окна настроек в моем приложении Swift macOS.

Одной из настроек, которые мне необходимо сохранить, является массив предустановок, определенный следующим классом:

class Preset: NSObject {
    var name = "abc"
    var value = 123

    override init() {
        super.init()
    }
}

Поэтому мне нужно сохранить переменную типа [Presets]. Визуальное представление в моем окне предпочтений - NSTableView, привязанное к NSArrayController.

Я следовал этому руководству, чтобы настроить мои привязки. При запуске приложения и попытке добавить новый пресет (нажав кнопку +) я получаю следующие ошибки:

[User Defaults] Attempt to set a non-property-list object (...) as an NSUserDefaults/CFPreferences value for key presets
[General] Attempt to insert non-property list object (...) for key presets

Я пытался реализовать протоколы Codable и NSCoding, но ошибка сохраняется.

При поиске похожих вопросов в переполнении стека (например, это или это ), кажется, что решение будет включать NSKeyedArchiver и NSKeyedUnarchiver. Это кажется достаточно простым, если вы вручную запускаете загрузку и сохранение. К сожалению, я не вижу, как использовать эти классы вместе с NSUserDefaultsController.

1 Ответ

0 голосов
/ 28 января 2019

Я решил проблему, подклассифицировав NSArrayController следующим образом (см. Комментарий Хэмиша к моему другому вопросу , который был последним отсутствующим фрагментом головоломки, чтобы сделать этот родовой):

extension Encodable {
    fileprivate func encode(to container: inout SingleValueEncodingContainer) throws {
        try container.encode(self)
    }
}

struct AnyEncodable: Encodable {
    var value: Encodable
    init(_ value: Encodable) {
        self.value = value
    }
    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try value.encode(to: &container)
    }
}

class NSEncodableArrayController: NSArrayController {
    override func addObject(_ object: Any) {
        let data = try! PropertyListEncoder().encode(AnyEncodable(object as! Encodable))
        let any = try! PropertyListSerialization.propertyList(from: data, options: [], format: nil)

        super.addObject(any)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...