Anyway, if you have a RubyCocoa project that needs a little bit of shininess, it may be surprisingly easy (and satisfying) to quickly port it over to MacRuby. I just spent about 4 hours converting a fairly sophisticated app (aside from its MIDI interface, which is a bit more tricky, but you probably won’t be dealing with that).
My first stop was this post, a very nice summary of the basic steps that need to be taken. However, I encountered quite a few additional snags, and I thought I’d post them just in case you, random internet denizen, want to skip them all together. Most of them are covered in the MacRuby docs, of course, but they’re here in a nice digestible table format so you can more easily knock out your conversion. Because as fun as prettying up your code is, you’d still rather be adding functionality, right?
| RubyCocoa | MacRuby |
|---|---|
| The basics | |
|
ib_outlet :property |
attr_writer :property |
|
ib_action :method def method(sender)... |
# Just ditch the ib_action call! def method(sender)... |
| Key-value coding (KVC) | |
|
kvc_accessor :property |
attr_accessor :property |
|
# Default setter automatically notifies property = 'new hotness' |
# Have to use notifying method (for now...) setValue 'new hotness', forKey:'property' |
| Setting an action selector | |
|
@table.setDoubleAction :doubleClick |
@table.setDoubleAction 'doubleClick:' |
| Dealing with Cocoa’s funky named parameters | |
|
# Parameter names are included in method name, # separated by underscores; values follow # in sequential order year.setValue_forKey 525600, 'minutes' |
# Only the first parameter name ("value") is # included in the method signature; the rest can be # defined with Ruby 1.9's named parameter support: year.setValue 525600, forKey:'minutes' # Or, alternatively, a hash: year.setValue 525600, :forKey => 'minutes' |
| Overriding Cocoa’s funky named parameters | |
|
def drawInteriorWithFrame_inView(frame, controlView) |
def drawInteriorWithFrame(frame, inView:controlView) |
| Calling the current method in the superclass | |
|
super_drawInteriorWithFrame_inView(frame, controlView) |
super # Now that's what I'm talking about! |
| Instantiating collections | |
|
array = NSMutableArray.alloc.init hash = NSMutableDictionary.alloc.init |
array = [] # It's a real NSMutableArray! hash = {} # It's a real NSMutableDictionary! |
| Instantiating objects | |
|
table = NSArrayController.alloc.init |
table = NSArrayController.new |
| Defining class initializers | |
|
def init super_init # If a Cocoa subclass # Do stuff self end |
def initialize super # If a Cocoa subclass # Do stuff. Note: you can still override #init, # but then you must return self. end |
ROOT = NSBundle.mainBundle.resourcePath.fileSystemRepresentation
Dir.glob("#{ROOT}/**/*.rb").each do |file|
if file != File.basename(__FILE__)
require(file)
end
end
And that’s just for starters! If I remember or encounter anything else, I’ll be sure to append this post. And don’t you dare think this is conclusive – the wonderful folks working on HotCocoa have been streamlining things for even greater efficiency, so be sure to check that out.








Hi Mike,
Very nice article! Thanks for taking the time to write this!
2 small things:
1) It is also possible to do NSTableview.new in RubyCocoa. However this example is confusing, since you are supposed to go through -[NSView initWithFrame:] when creating views.
2) If you want to overwrite the default -[NSObject init] method in MacRuby, you must still return self. However if you decide to overwrite #initialize (which -init calls], it is not necessary to return self here (as in pure Ruby).
Would you be interested to convert your blog post as an article for our website (http://www.macruby.org/documentation.html)? I think it would be awesome to have a “MacRuby for RubyCocoa programmers” short guide.
Laurent