LoginSignup
5
5

More than 5 years have passed since last update.

Ruby FFI bindings for the OSX Cocoa API を使うと楽にMacアプリが書ける

Posted at

Ruby FFI bindings for the OSX Cocoa API というものがあったので使ってみました。

インストール

activesupport requires Ruby version >= 2.2.2.とあるので、まず独自にRubyをインストール。Homebrewを使ってみました。

brew install ruby

最新バージョンのRubyが使えるのを確認後、cocoa gem をインストール。

gem install cocoa

準備は以上です。

サンプルコード

require 'cocoa'

Cocoa::NSAutoreleasePool.new

app = Cocoa::NSApplication.sharedApplication
app.setActivationPolicy Cocoa::NSApplicationActivationPolicyRegular
app.activateIgnoringOtherApps true

alert = Cocoa::NSAlert.alloc.init.autorelease
alert.setMessageText "Hello world!"
alert.runModal

Hello Alert Box

メモリ管理は NSAutoreleasePool を使用した半自動管理なコードになるようです。

もう少しMacアプリっぽくウィンドウアプリを書いてみました。

hello.cocoa.rb
#!/usr/local/bin/ruby

require "cocoa"
Cocoa::NSAutoreleasePool.new

class UserInterface < Cocoa::NSObject
  attr_accessor :window, :btnHello, :btnGoodbye
  def init
    @window = NSWindow.alloc.initWithContentRect(NSRect.new(x: 0, y: 0, width: 250, height: 100), 
      styleMask: NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask, 
      backing: NSBackingStoreBuffered, 
      defer: false).autorelease
    @window.setTitle "Welcome to Ruby"
    @window.setReleasedWhenClosed true
    @window.center

    @btnHello = NSButton.alloc.initWithFrame(NSRect.new x: 10, y: 10, width: 110, height: 80).autorelease
    @btnHello.setTitle "Hello!"
    @btnHello.setBezelStyle NSRegularSquareBezelStyle
    @btnHello.setSound NSSound.alloc.initWithContentsOfFile("/System/Library/Sounds/Tink.aiff", byReference:true).autorelease
    @window.contentView.addSubview btnHello

    @btnGoodbye = NSButton.alloc.initWithFrame(NSRect.new x: 130, y: 10, width: 110, height: 80).autorelease
    @btnGoodbye.setTitle "Goodbye!"
    @btnGoodbye.setBezelStyle NSRegularSquareBezelStyle
    @btnGoodbye.setSound NSSound.alloc.initWithContentsOfFile("/System/Library/Sounds/Basso.aiff", byReference:true).autorelease
    @window.contentView.addSubview btnGoodbye

    return self
  end
end

class AppDelegate < Cocoa::NSObject
  def init
    @ui = UserInterface.alloc.init.autorelease
    @ui.btnHello.setAction :hello
    @ui.btnGoodbye.setAction :goodbye
    return self
  end

  def hello sender
    puts "hello"
  end

  def goodbye sender
    puts "goodbye"
    $application.terminate nil
  end

  def applicationDidFinishLaunching notification
    @ui.window.makeKeyAndOrderFront self
  end

  def applicationShouldTerminateAfterLastWindowClosed sender
    return true
  end

end

$application = Cocoa::NSApplication.sharedApplication
$application.setActivationPolicy Cocoa::NSApplicationActivationPolicyRegular
$application.setDelegate AppDelegate.alloc.init.autorelease
$application.activateIgnoringOtherApps true
$application.run

ruby.cocoa.jpg

コツはサブクラス定義でCocoa::NSObject由来のクラスを継承する、サブクラスのイニシャライザーでselfを返す、autoreleaseを忘れずに、と言ったところでしょうか。

RubyでMacアプリを書けるのは楽しいです。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5