ib_outlet Doesn’t Create Accessors
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:0×2297be class=‘PathController’ id=0×534ec0>
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:0×2297be class=‘PathController’ id=0×534ec0> (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.