From: Brian M. <ma...@ex...> - 2008-05-17 19:08:42
|
It seems as if RubyCocoa's key-value observing works differently in some ways than Objective-C's would. Is this intentional? An incomplete implementation? The real question: is it stable behavior an app can depend upon? Here's the difference in the most important case (where you've declared the value with kvc_accessor): - setting the variable directly (var= or setVar) behaves like Objc: observeValueForKeyPath... is called - setting it with setValue_forKey does not: observeValueForKeyPath... is called twice (once, I assume, for willChangeValueForKey and once for didChangeValueForKey) In Objc, it'd be called once. Details: ============= Here's Objective-C: A Watcher object watches an Observed object like this: - (id) initWatching: (id) observed { [observed addObserver: self forKeyPath: @"value" options: 0 context: NULL]; return self; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { NSLog(@"observed %@\n", keyPath); } Here a third object triggers observation: Observed *observed = [[Observed alloc] init]; Watcher *watcher = [[Watcher alloc] initWatching: observed]; NSLog(@"Setting directly."); observed.value = @"new value"; // The result is "observed value" NSLog(@"Setting kvcly."); [observed setValue: @"newer value" forKey: @"value"]; // The result is "observed value" ============ The Ruby code: require 'osx/cocoa' class Observed < OSX::NSObject if ARGV[0] == 'kvc' kvc_accessor :value else attr_accessor :value end end class Watcher < OSX::NSObject def initWatching(observed) init observed.addObserver_forKeyPath_options_context(self, 'value', 0, nil) self end def observeValueForKeyPath_ofObject_change_context( keyPath, object, change, context) puts "#{object} changed #{keyPath}" end end observed = Observed.alloc.init watcher = Watcher.alloc.initWatching(observed) puts "Setting directly" observed.value = 5 # Nothing if plain accessor; sees change if kvc_accessor. puts "Setting via setValue method" observed.setValue(5) # Nothing if plain accessor; sees change if kvc_accessor. puts "setting kvcly" observed.setValue_forKey(5, 'value') # Gets two messages (presumably willChange and hasChanged) observed.removeObserver_forKeyPath(watcher, 'value') ----- Brian Marick, independent consultant Mostly on agile methods with a testing slant www.exampler.com, www.exampler.com/blog, www.twitter.com/marick |
From: Patrick G. <pge...@wa...> - 2008-05-19 15:07:08
|
> It seems as if RubyCocoa's key-value observing works differently in > some ways than Objective-C's would. Is this intentional? An incomplete > implementation? The real question: is it stable behavior an app can > depend upon? Checking the source of kvc_accessor from oc_import.rb : declaring an accessor with kvc_accessor will call KVO methods in the setter. setValue_forKey calls KVO methods + accessor, which again calls KVO methods, thus the 2 notifications. I don't know if that's correct. def kvc_accessor(*args) kvc_reader(*args) kvc_writer(*args) end def kvc_writer(*args) args.flatten.each do |key| setter = key.to_s + '=' attr_writer(key) unless method_defined?(setter) alias_method kvc_internal_setter(key), setter self.class_eval <<-EOE_KVC_WRITER,__FILE__,__LINE__+1 def #{kvc_setter_wrapper(key)}(value) willChangeValueForKey('#{key.to_s}') send('#{kvc_internal_setter(key)}', value) didChangeValueForKey('#{key.to_s}') end EOE_KVC_WRITER alias_method setter, kvc_setter_wrapper(key) end end |
From: kimura w. <ki...@us...> - 2008-05-28 14:58:52
|
Thanks for your reporting, This is a bug of RubyCocoa. I fixed this bug at svn trunk r2202-2203. On Sat, 17 May 2008 14:08:28 -0500, Brian Marick wrote: > It seems as if RubyCocoa's key-value observing works differently in > some ways than Objective-C's would. Is this intentional? An incomplete > implementation? The real question: is it stable behavior an app can > depend upon? > -- kimura wataru |
From: Brian M. <ma...@ex...> - 2008-05-28 16:44:52
|
Thanks. I submitted a bug report+workaround at <http://sourceforge.net/tracker/index.php?func=detail&aid=1970883&group_id=44114&atid=438476 > Did you fix it by having kvc_writer define automaticallyNotifiesObserversForKey to be false? Doing that manually passes my tests. On May 28, 2008, at 9:58 AM, kimura wataru wrote: > Thanks for your reporting, > > This is a bug of RubyCocoa. > I fixed this bug at svn trunk r2202-2203. > > On Sat, 17 May 2008 14:08:28 -0500, Brian Marick wrote: >> It seems as if RubyCocoa's key-value observing works differently in >> some ways than Objective-C's would. Is this intentional? An >> incomplete >> implementation? The real question: is it stable behavior an app can >> depend upon? >> > -- > kimura wataru > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Rubycocoa-talk mailing list > Rub...@li... > https://lists.sourceforge.net/lists/listinfo/rubycocoa-talk ----- Brian Marick, independent consultant Mostly on agile methods with a testing slant www.exampler.com, www.exampler.com/blog, www.twitter.com/marick |
From: kimura w. <ki...@us...> - 2008-05-29 14:14:21
|
Hi Brian, On Wed, 28 May 2008 11:44:37 -0500, Brian Marick wrote: > Thanks. I submitted a bug report+workaround at > <http://sourceforge.net/tracker/index.php?func=detail&aid=1970883&group_id=44114&atid=438476 > > > > Did you fix it by having kvc_writer define > automaticallyNotifiesObserversForKey to be false? Doing that manually > passes my tests. Yes. I fixed the bug, you reported in bug#1970883, of kvc_writer at r2023. Just now, I fixed the same bug of kvc_array_accessor at r2025. Thanks again, -- kimura wataru |