RubyCocoa is one of the most fascinating tools on OSX. It makes it more than easy to rapidly prototype and try ideas with Cocoa. But unfortunately, out of the box, a RubyCocoa project seems to require an Objective-C shell to start it up. That means firing up XCode for every single prototype you’re playing with.

It only seems that way, though. A quick look behind the scenes reveals that all that shell does is:

  • start the ruby environment
  • ‘require’ all included ruby scripts
  • and runs NSApplicationMain

The first two, I can obviously do on my own. The third provides the main loop for all NSApplications. But you can’t simply call it from Ruby - it requires you to have an Info.plist. Again, too much baggage for quick & dirty prototypes. The goal is to have one ruby file to play around in.

That one is a bit trickier to find out, but after digging around in Apple’s documentation, it turns out there is a decent explanation in the overview for NSApplication

For future reference, this is what it does:


void NSApplicationMain(int argc, char *argv[]) {
    [NSApplication sharedApplication];
    [NSBundle loadNibNamed:@"myMain" owner:NSApp];
    [NSApp run];
}
 

Now we’re getting somewhere. This can actually be completely duplicated in Ruby. Since I might want to quit my application, I’ve thrown in a window that shuts down the application when closed.


require ‘OSX/cocoa’

class CloseDelegate < OSX::NSObject
  def windowWillClose( sender )
    OSX::NSApp.terminate_ sender
  end
end

# Instantiate the shared App
OSX::NSApplication.sharedApplication

window = OSX::NSWindow.alloc
window.initWithContentRect_styleMask_backing_defer_(
  OSX::NSMakeRect(50,50,200,400),
  OSX::NSTitledWindowMask
    + OSX::NSClosableWindowMask,
  OSX::NSBackingStoreBuffered, true)

window.setDelegate CloseDelegate.alloc.init
window.makeKeyAndOrderFront nil

# run the main loop
OSX::NSApplication.sharedApplication.run

 

Or just download standalone.rb

Leave a reply