Re: Bind NSTableView to array of dictionaries in user defaults
> On May 5, 2016, at 7:47 PM, Jerry Krinockwrote: > > After reading Quincey’s reply, I had concluded that this is one of those > cases where Cocoa Bindings requires additional “glue”, which defeats one of > the two purposes of Cocoa Bindings. But it would be very cool if there were > some configuration change that would be make this work in both directions. > It seems like we’re really close. > > I’m accustomed to doing this kind of code-less binding to a Core Data model, > wherein it “just works”. That’s not surprising, because of course Core Data > knows the data model in great detail. It can observe everything. Trying out your example it looks like both you and Quincey may be correct, but on the opposite ends. The issue appears to be something with how view-based tables work, rather than NSArrayController. If you substitute with a cell-based table, it works flawlessly. The issue seems to involve binding through objectValue, so I guess you are back to needing some kind of glue code. I was able to get it to work properly by proxy-ing the array in the app delegate, so this must specifically be an interaction between view-based tables and NSUserDefaultsController. I would file a radar, FWIW. HTH, Keary Suska Esoteritech, Inc. "Demystifying technology for your home or business" ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Bind NSTableView to array of dictionaries in user defaults
Thank you, Keary. > On 2016 May 05, at 13:47, Keary Suskawrote: > > >> On May 5, 2016, at 7:44 AM, Jerry Krinock wrote: >> >> So I bound the Content Array of the array controller to the 'values' of the >> shared user defaults controller with an arbitrary key path, which pleasantly >> became the key to the array in the user defaults. I set "Handles Content as >> Compound Values” to ON. > > Is this a single or multi-level keypath? single… Bind to = Shared User Default Controller Controller Key = values Model Key Path = persons Cocoa creates the “lower” levels (firstName and lastName in my demo) as dictionary keys automatically. > IIRC the issues Quincy is referring to are common in a multiple-object > keypath, especially for defaults as NSUserDefaultsController uses some > internal trickery to edit the immutable collections maintained by > NSUserDefaults. Yes, this is not that. > I cannot replicate this behavior with a straightforward approach. Can you > create a reduction that replicates the behavior? https://github.com/jerrykrinock/ArrayDictionaryDefaultsDemo >> In the array controller's content, the object attribute is always changed as >> expected. So, the problem is the binding of the array controller content to >> user defaults, and I think the explanation is that, as always, KVO is >> “shallow”. Observing an array does not observe changes to its elements. > > This is curious—how do you know that the attribute is being changed as > expected? By stopping execution and printing the array controller’s “content” in the debugger. I see the new value in the dictionary. > Is it that it shows in the UI, but is not persisted? Yes, when I type a new value into the table, it stays there. But it goes back to the old value upon relaunch. > Have you changed the default value of -[NSUserDefaultsController > appliesImmediately]? I just tried it. It did not help. I had already tried -[NSUserDefaults synchronize] after changing the value, which I presume does the same thing “manually”. * * * After reading Quincey’s reply, I had concluded that this is one of those cases where Cocoa Bindings requires additional “glue”, which defeats one of the two purposes of Cocoa Bindings. But it would be very cool if there were some configuration change that would be make this work in both directions. It seems like we’re really close. I’m accustomed to doing this kind of code-less binding to a Core Data model, wherein it “just works”. That’s not surprising, because of course Core Data knows the data model in great detail. It can observe everything. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Bind NSTableView to array of dictionaries in user defaults
> On May 5, 2016, at 7:44 AM, Jerry Krinockwrote: > > In an OS X app, I wanted to bind a table of objects, each represented by a > dictionary, to an array of dictionaries in user defaults. > > So I bound the Content Array of the array controller to the 'values' of the > shared user defaults controller with an arbitrary key path, which pleasantly > became the key to the array in the user defaults. I set "Handles Content as > Compound Values” to ON. Is this a single or multi-level keypath? IIRC the issues Quincy is referring to are common in a multiple-object keypath, especially for defaults as NSUserDefaultsController uses some internal trickery to edit the immutable collections maintained by NSUserDefaults. > Result: The table is populated as expected from user defaults when its window > opens, and all works and persists as expected if user adds or deletes an > object (row). But changes to object attributes are persisted only for new > objects, and only if user adds *another* object before quitting. I cannot replicate this behavior with a straightforward approach. Can you create a reduction that replicates the behavior? > In the array controller's content, the object attribute is always changed as > expected. So, the problem is the binding of the array controller content to > user defaults, and I think the explanation is that, as always, KVO is > “shallow”. Observing an array does not observe changes to its elements. This is curious—how do you know that the attribute is being changed as expected? Is it that it shows in the UI, but is not persisted? Have you changed the default value of -[NSUserDefaultsController appliesImmediately]? Keary Suska Esoteritech, Inc. "Demystifying technology for your home or business" ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Bind NSTableView to array of dictionaries in user defaults
On May 5, 2016, at 06:44 , Jerry Krinockwrote: > > I’m disapointed that the “magic of Cocoa Bindings” does not seem to provide a > simple “code-less” solution to this simple requirement. Did I miss something? It’s never been possible to bind “through” a NSArray or NSSet. AFAICT, that’s what’s gone wrong in your scenario, the involvement of user defaults here being a decorative factor only. If you think about it, it should be clear that this “defect” is the same “How does my object know if any of its properties has changed?” question that comes up from time to time. There isn’t any good, straightforward way. You can, for example, override ‘setValue:forKey:’ in the class of the array elements. That will give you a single point of intervention when any of the element properties are changed via KVC, as happens with bindings-related changes from the UI. But the element doesn’t automatically know what array it is a member of, so you’d need ad-hoc code to propagate the change to the specific property of the specific object that the array represents. (That is, it isn’t even enough to know the array.) In this case, the simplest solution is probably to implement a custom setter (if Obj-C, or a ‘didSet’ accessor if Swift) for each property of each element that triggers a re-save of the user defaults. Alternatively, if what is at each index of the array is semantically fixed, you could save each element in user defaults under a unique key and avoid the array. Or, you might be able to use a NSDictionary instead of an array, which shouldn’t exhibit this “bind-through” limitation, because changes to NSMutableDictionary keys are KVO compliant.) ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Bind NSTableView to array of dictionaries in user defaults
In an OS X app, I wanted to bind a table of objects, each represented by a dictionary, to an array of dictionaries in user defaults. So I bound the Content Array of the array controller to the 'values' of the shared user defaults controller with an arbitrary key path, which pleasantly became the key to the array in the user defaults. I set "Handles Content as Compound Values” to ON. Result: The table is populated as expected from user defaults when its window opens, and all works and persists as expected if user adds or deletes an object (row). But changes to object attributes are persisted only for new objects, and only if user adds *another* object before quitting. In the array controller's content, the object attribute is always changed as expected. So, the problem is the binding of the array controller content to user defaults, and I think the explanation is that, as always, KVO is “shallow”. Observing an array does not observe changes to its elements. I’m disapointed that the “magic of Cocoa Bindings” does not seem to provide a simple “code-less” solution to this simple requirement. Did I miss something? Jerry I also tried this using a custom object instead of an NSMutableDictionary as the content class of the array controller, making my custom class conform to NSCoding, and inserting a NSKeyedUnarchiveFromData value transformer into the binding. Result: Exactly the same deficiency. ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com