NSUserDefaultsController: “Attempt to set a non-property-list object … as an NSUserDefaults/CFPreferences value for key …”

◇◆丶佛笑我妖孽 提交于 2019-12-25 01:09:01

问题


I'm trying to use NSUserDefaultsController to implement a Preferences window in my Swift macOS app.

One of the settings that I need to persist is an array of presets, as defined by the following class:

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

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

Therefore, I need to persist a variable of type [Presets]. The visual representation in my Preferences window is an NSTableView, bound to an NSArrayController.

I followed this tutorial to set up my bindings. When running the app and trying to add a new preset (by clicking the + button), I get the following errors:

[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

I've tried implementing the Codable and NSCoding protocols, but the error persists.

From searching similar questions in Stack Overflow (such as this or this), it appears the solution would involve NSKeyedArchiver and NSKeyedUnarchiver. That appears simple enough to do if you're manually triggering loads and saves. Unfortunately I don't see how to use these classes along with NSUserDefaultsController.


回答1:


I solved the problem by subclassing NSArrayController as follows (see comment by Hamish to my other question, which was the last missing piece of the puzzle to make this generic):

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


来源:https://stackoverflow.com/questions/54375863/nsuserdefaultscontroller-attempt-to-set-a-non-property-list-object-as-an-n

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!