Lately, I’ve been having fun with RubyCocoa while reading Brian Marick‘s RubyCocoa. It’s an entertaining book, and I really like RubyCocoa itself. But I hit a little gotcha. Take the following code:

PathController.rb
 1 require 'osx/cocoa'
 2 
 3 class PathController < OSX::NSObject
 4   ib_outlet :path, :events
 5   ib_action :choosePath
 6   
 7   def choosePath(sender)
 8     panel = OSX::NSOpenPanel.openPanel
 9     panel.canChooseFiles          = false
10     panel.canChooseDirectories    = true
11     panel.allowsMultipleSelection = false
12 
13     result = panel.runModal
14     if result == OSX::NSFileHandlingPanelOKButton then
15       self.path.title = panel.filename
16     end
17   end
18 end

What could be wrong with this? Turns out #ib_oulet does not define accessors for the instance variables it defines. Look at the exception:

 1 OSX::OCMessageSendException: Can't get Objective-C method signature for selector 'events' of receiver #<PathController:0x2297be class='PathController' id=0x534ec0>
 2   /Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/oc_wrapper.rb:50:in `ocm_send'
 3   /Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/oc_wrapper.rb:50:in `method_missing'
 4   /Users/francois/Projects/fsevtest/build/Debug/fsevtest.app/Contents/Resources/PathController.rb:27:in `choosePath'
 5   /Users/francois/Projects/fsevtest/build/Debug/fsevtest.app/Contents/Resources/rb_main.rb:22:in `NSApplicationMain'
 6   /Users/francois/Projects/fsevtest/build/Debug/fsevtest.app/Contents/Resources/rb_main.rb:22
 7 /Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/oc_wrapper.rb:50:in `ocm_send': Can't get Objective-C method signature for selector 'events' of receiver #<PathController:0x2297be class='PathController' id=0x534ec0> (OSX::OCMessageSendException)
 8   from /Library/Frameworks/RubyCocoa.framework/Resources/ruby/osx/objc/oc_wrapper.rb:50:in `method_missing'
 9   from /Users/francois/Projects/fsevtest/build/Debug/fsevtest.app/Contents/Resources/PathController.rb:27:in `choosePath'
10   from /Users/francois/Projects/fsevtest/build/Debug/fsevtest.app/Contents/Resources/rb_main.rb:22:in `NSApplicationMain'
11   from /Users/francois/Projects/fsevtest/build/Debug/fsevtest.app/Contents/Resources/rb_main.rb:22

From the obscure message, I gathered this was some kind of NoMethodError (why couldn’t they use an exception with a good name?) That was Sunday morning. Sunday evening, I suddenly had a flash that ib_outlet wouldn’t define an accessor. Changed my code to use the instance variable instead:

PathController.rb
1 if result == OSX::NSFileHandlingPanelOKButton then
2   @path.title = panel.filename
3 end

Lo and behold! It worked beautifully.

Search

Your Host

A picture of me

I am François Beausoleil, a Ruby on Rails and Scala developer. During the day, I work on Seevibes, a platform to measure social interactions related to TV shows. At night, I am interested many things. Read my biography.

Top Tags

Books I read and recommend

Links

Projects I work on

Projects I worked on