[Rubycocoa-devel 1365] kvc setter results in recursive loop

Back to archive index

Eloy Duran eloy.****@gmail*****
Tue Jun 24 00:33:21 JST 2008


Hi,

I know this will probably be a waste of energy since most time is  
spend on MacRuby, but here goes anyways.
I have used kvc_accessors etc on several apps in the past and it has  
always not felt 100% right to me,
but I was too lazy to take a look at it. Most of the times if I needed  
to do stuff with the variables I override #rbSetValue_forKey

This has always managed me to be able to write working code, but  
during testing it breaks horribly.
Today I was cleaning up some code and wanted to have all my tests run  
in one go so I get nice output of the total tests passed/failed.
So what happens? The following is a small sample from endless recursion:

	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `_kvc_internal_host='
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `send'
	/Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/ 
oc_import.rb:510:in `host='

I took a quick look at oc_import.rb, this is the method:

If oc_import.rb:501 is patched like so it works:

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

If oc_import.rb:501 is patched like so it works:

def kvc_writer(*args)
   args.flatten.each do |key|
     setter = key.to_s + '='
     #attr_writer(key) unless method_defined?(setter) # <= unnecessary?
     #alias_method kvc_internal_setter(key), setter # <= unnecessary?
     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) # <= unnecessary?
         @#{key} = value # <= added!
         didChangeValueForKey('#{key.to_s}')
       end
     EOE_KVC_WRITER
     alias_method setter, kvc_setter_wrapper(key)
   end
end

Ok so I just quickly hacked some things to see what actually goes  
wrong and the problem
is really some recursive setter stuff. I understand why one might have  
added this, but I *think* it's a case of YAGNI.

The real problem with this is that there are no tests at all that  
contain "kvc" and I couldn't find any sample code
that overrode the setter methods... :(

So even if I would like to clean this up, I'd have no idea what I  
would break.
I have code at http://github.com/alloy/passengerpane/tree/master which  
exhibits the problem.
If you run the "rake test" task you will see where it goes wrong. The  
"rake test_normal" task is
what I have to use now to circumvent these problems.

Cheers,
Eloy




More information about the Rubycocoa-devel mailing list
Back to archive index