I have a cocoa binding between UserDefaults
and a TextField
setup via IB:
This works great, on every launch of the app the TextField
will persist it's value
However, I also want to read this string value programmatically in other places in code. I have tried basically all of the UserDefaults.standard
calls:
guard let supplierData = UserDefaults.standard.data(forKey: "singleSupplierDownloadName") else {return}
returns: ▿ 145 bytes
- count : 145 ▿ pointer : 0x0000608000187ae0
- pointerValue : 106102873684704
UserDefaults.standard.string(forKey:)
returns nil
object(forKey:)
returns this:
▿ Optional<Any>
- some : <62706c69 73743030 d4010203 04050609 0a582476 65727369 6f6e5824 6f626a65 63747359 24617263 68697665 72542474 6f701200 0186a0a2 07085524 6e756c6c 57746573 74696e67 5f100f4e 534b6579 65644172 63686976 6572d10b 0c54726f 6f748001 08111a23 2d32373a 40485a5d 62000000 00000001 01000000 00000000 0d000000 00000000 00000000 00000000 64>
Given this, I decided to try to do something with the Data
I retrieved with data(forKey:)
(lldb) po String(data: supplierData, encoding: .ascii)
▿ Optional<String>
- some : "bplist00Ô\u{01}\u{02}\u{03}\u{04}\u{05}\u{06}\t\nX$versionX$objectsY$archiverT$top\u{12}\0\u{01} ¢\u{07}\u{08}U$nullWtesting_\u{10}\u{0F}NSKeyedArchiverÑ\u{0B}\u{0C}Troot\u{01}\u{08}\u{11}\u{1A}#-27:@HZ]b\0\0\0\0\0\0\u{01}\u{01}\0\0\0\0\0\0\0\r\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0d"
I played around with the different encoders, and it was all junk. Until I used ascii, you can see that there is hints of English in there, "NSKeyedArchiver", "unarchiver", etc. Made me believe that this data is actually not just a String, but a compressed String (archived)
so then I thought maybe I need to initialize an NSKeyedUnarchiver
,
(lldb) po NSKeyedUnarchiver(forReadingWith: supplierData)
<NSKeyedUnarchiver: 0x60800010beb0>
But from there... I don't know what to do. Everything I ask from the NSKeyedUnarchiver
returns nil
Am I on the right track?
How can I read this string value stored in the Shared User Defaults Controller via Cocoa Bindings?
The fix was not to use NSKeyedUnarchiveFromData
as the value transformer on the binding (or any value transformer, at all).
When you use a value transformer, that makes the binding system transform the value from the view into some other value for the model to store and, when it retrieves a value from the model, to transform it to a value that the view can work with. In your case, a text field works naturally with string values and so does the user defaults system, so there's no need or benefit to transforming to/from data objects.
The main use for transforming via NSKeyedUnarchiveFromData
is for values of types that can't be directly stored in property lists, such as color objects.