VisualStudio を用いた Cocoa 開発
概要
はじめに
Mac の開発をやってみようと Xcode を開いてみたが Objective-C を目の前にして途方にくれる。C#(VB.NETでも可)ならいくらでも書けるのに…!
そんな Windows フォーム開発者に朗報です。Mac 版 Mono に付属している Cocoa# を使えば、慣れ親しんだ VisualStudio で Mac 用のアプリを作れるのです。
対象読者
- Windows Forms (1.1/2.0) による開発経験のある人。
- VisualStudio 2005 のインテリセンスが手放せない人。
- Mac の開発をやってみたいけど、Objective-C わけわからん人。
この文章でやること
- Mac 用アプリケーションを作る
- ロジック部分を VisualStudio 2005 で開発する。
- VisualStudio で .NET のコンソールアプリケーションを新規作成。
- Cocoa# を参照設定する
- コード書いてビルドする
- インターフェイスを作って実行ファイルにまとめる
- Interface Builder でインターフェイスを作る
- Mono 付属の macpack でアプリケーションを生成する
Mac 用アプリの考え方
ユーザーインターフェイスとコードの完全分離
Mac では Nib ファイルに格納されたインターフェイス部分が、実行しているクラスのプロパティを参照する形で動作します。
アウトレットとアクション
インターフェイスとのやりとりの際に出てくる重要な概念です。えびは最初どっちがどっちだったか混乱しました。 重要な概念なので、よく確認しておきましょう。
- アウトレット
- 出力。画面に表示される値のことです。
- アクション
- 入力。Windows Forms でいうイベント。
よくわかりませんが、MVCモデルを使ってる、ともいうそうです。
準備
環境の準備
今回使用した環境は以下のとおりです。詳細なスペックはマシン紹介へ。
- Windows側
- はるか (デスクトップ/Windows XP SP2)
- Mac側
- きらり (MacBook/Mac OS 10.4.8)
- ファイルサーバー
- あすか (サーバー/Fedora Core 4)
Windows 側の準備
VisualStudio2005 をインストールしておいてください。 このチュートリアルでは Professional を使用していますが、無料の Express Edition でもかまいません。
Mac 側の準備
Xcode を Mac OS のDVDからインストールしておいてください。
Mono プロジェクトから「Mono 1.2_rc0 Framework - x86 (Stable)」を入手します。 dmg ファイルをマウントするとインストーラが入っているのでインストールします。
http://www.mono-project.com/Downloads
インストーラによるインストールが終わったら、ターミナルを起動して以下のコマンドを実行します。
set | grep -i pkg
このコマンドを実行して、何も出てこなければ ~/.profile に以下の記述をします。
export PKG_CONFIG_PATH=/Library/Frameworks/Mono.framework/Versions/Current/lib/pkgconfig
何か出てきた場合はこの記述をします。
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/Library/Frameworks/Mono.framework/Versions/Current/lib/pkgconfig
インストールが終わったら Cocoa# のアセンブリを抽出します。以下のフォルダを表示させます。
Machintosh HD>ライブラリ>Frameworks>Mono.framework>Versions>Current>lib>mono>cocoa-sharp
このフォルダには2つのファイルのエイリアスがあります。
右クリック*1し、「オリジナルを表示」をクリックすると実体がでてきますのでこのファイルを2つともデスクトップへ「コピー」しておきます。*2
共有フォルダを準備
この準備はシームレスな開発を行ううえで非常に重要です :)
Windows/Mac 双方から読み書きできる開発用ファイルサーバーを用意します。
今回は、ファイルサーバーの Samba 共有に development というフォルダを用意しました。もちろん Windows機、Mac機 の共有機能を使うのでもOKです。
先ほど Mac 上で抽出した Cocoa# のアセンブリを delelopment フォルダの中にフォルダを作ってここに移動しておきます。
その後、プロジェクトファイル用のフォルダを用意して以下のようにしておきます。
- Development
- \CocoaSharpRuntime
- cocoa-sharp.dll
- webkit-sharp.dll
- \VisualStudio2005
- (各プロジェクト)
- \CocoaSharpRuntime
Windows 機はネットワークドライブを設定しておくと便利です。
なお、Mac 機からWindows共有にアクセスするには Finderの「移動>サーバーへ接続」を選び、「smb://[コンピュータ名]」を入力すればOKです。
開発チュートリアル
とりあえず動かす
VisualStudio 2005 でプロジェクトを作成する
VisualStudio 2005 を起動して「コンソールアプリケーション」を作成します。プロジェクト名は「HelloCocoa」、場所は先ほど作ったプロジェクト用フォルダにします。
コンソールアプリケーションの基本構成が作成され、空のクラスファイルが生成されます。
次に、ソリューションエクスプローラの参照設定を右クリックして、共有フォルダのCocoaSharpRuntimeに保存した2つのDLLのうち「cocoa-sharp.dll」を参照します。
この状態でコードを記述します。
using System;
using System.Collections.Generic;
using System.Text;
using Cocoa;
namespace HelloCocoa
{
class Program
{
static void Main(string[] args)
{
Application.Init();
Application.LoadNib("HelloCocoa.nib");
Application.Run();
}
}
}
追加したのは4行、Cocoa 名前空間を using しました。 メイン部分に記述したコードは、上から順にアプリケーション初期化、インターフェイス読み込み、アプリケーション実行です。
記述があればアプリケーションをビルドします。「ビルド」メニューから「ソリューションのビルド」です。*3
Interface Builder でインターフェイスを作成する
Mac で先ほど作成したプロジェクトの csproj ファイルがある階層へ移動します。 ここに「interface」フォルダと「build」フォルダを用意します。
Interface Builder を起動します。*4 Starting Point ウィンドウが出てきますので、Cocoa>Application を選択します。
出てきたウィンドウのうち、5つタブ*5のあるウィンドウの Instances タブから Window をダブルクリックしてウィンドウを出します。
次に、Cocoa-Controls のパレットのボタンのタブからボタンを、テキストのタブから System Font Text と書かれているテキストをウィンドウへドラッグします。
ここまでできたら、File メニューから Save as を選びます。ファイル名は HelloCocoa、保存先はこの節の最初に作った「interface」フォルダです。 これで、interface フォルダに HelloCocoa.nib というファイルが作成されます。*6
macpack でアプリケーションを作成する
必要なファイルが揃ったので、実行ファイルを作成します。
Mac でターミナルを起動し、csproj ファイルのあるフォルダへ移動します。*7 ディレクトリを移動したら、以下のコマンドを入力します
macpack -m:2 -n:HelloCocoa -o:./build -a:./bin/Debug/HelloCocoa.exe -r:./interface/HelloCocoa.nib
このコマンドを実行すると、build フォルダに HelloCocoa というアプリケーションが出来上がります。
実行すると先ほど作成したウィンドウが表示されます。
なお、macpack は出力先に既にアプリケーションファイルがあるとエラーが出て処理を中止します。 変更を加えて再度実行ファイルを作成する場合は事前に出力先のファイルを削除しておく必要があります。
アウトレット/アクションを処理する
Interface Builder で定義する
コントローラクラスを定義する
まず、C# で作成したアプリケーションと通信を行うコントローラクラスを定義します。 ここで定義したクラスのメンバ(アウトレット、アクション)を後ほど C# で記述することになるので覚えて置いてください。
Interface Builder の Classes タブを開き、虫眼鏡マークをクリックして NSObject を選び、 出てきた「NSObject」を右クリックして「Subclass NSObject」を選び「ApplicationController」と名づけます。
今作った「ApplicationController」をインスタンス化してこのアプリケーションで使えるようにします。 「ApplicationController」を右クリックして「Instantiate ApplicationController」を選びます。 タブが「Instances」に切り替わり、ApplicationController が出来ているはずです。
アウトレットを定義する
Classes タブに戻り、「ApplicationController」を右クリックして「Add Outlet to ApplicationController」を選びます。
すると、「ApplicationController Class Inspector」というパレットが開き、新しいアウトレットが入力できるようになっています。
ここに、プログラム側で操作するコントロールの名前と型を定義していきます。今回は以下のように定義しました。
- Outlet Name「label1」、Type「NSTextField」
- Outlet Name「mainWindow」、Type「NSWindow」
この後、実体と関連付けする必要があります。ちょっと特殊な操作なので注意してください。
Instances タブをクリックし、ApplicationController を選択します。次に、「controlキー」*8を押しながらApplicationController をドラッグし、System Font Text にドラッグします。
すると、インスペクタウィンドウで、どのアウトレットと関連付けするかをきいてきますので、「label1」を選んで「Connect」をクリックします。
今度は、ApplicationController から、Instances タブの Window のアイコンへcontrolキー押しながらドラッグします。関連付け先は「mainWindow」です。
更に、「Window」から「ApplicationController」へcontrolキー押しながらドラッグ、「delegate」へ接続します。
更に、「File's Owner」から「ApplicationController」へcontrolキー押しながらドラッグ、「delegate」へ接続します。*9
アクションを定義する
Classes タブに戻り、「ApplicationController」を右クリックして「Add Action to ApplicationController」を選びます。
すると、「ApplicationController Class Inspector」というパレットが開き、新しいアクションが入力できるようになっています。
ここに、C# 側で受信するイベントの名前を定義します。今回は以下のように定義しました。最後の「:」は必ずつける必要があり、記述を忘れても勝手に補完してくれます。
- buttonClick:
この後、実体と関連付けます。Instances タブをクリックし、フォームでザイナ上のボタンをcontrolキーを押しながらApplicationControllerへドロップします。
すると、インスペクタウィンドウで、どのアクションと関連付けするかをきいてきますので、「buttonClick:」を選んで「Connect」をクリックします。
これで定義は完了です。作成したインターフェイスを保存しておいてください。
VisualStudio で処理を記述する
VisualStudio に移動し、ソリューションエクスプローラのプロジェクトのところで右クリック、「追加>新しい項目」を選びます。
開いたウィンドウでクラスを選び、ApplicationControllerと名づけて追加します。
以下のように記述します。
using System;
using System.Collections.Generic;
using System.Text;
using Cocoa;
namespace HelloCocoa
{
/// <summary>
/// アプリケーションコントローラクラス
/// </summary>
/// <remarks>
/// Interface Builder で指定した同じ継承元、同じ名前のクラスを作成します。
/// また、Register 属性を付加します。
/// </remarks>
[Register]
class ApplicationController : Cocoa.Object
{
#region アウトレットの定義
// Interface Builder で指定した同じ名前、同じ型のパブリックフィールドを記述します。
// また、Connect 属性を付加します。
/// <summary>
/// System Font Text と対応
/// </summary>
[Connect]
public TextField label1;
/// <summary>
/// ウィンドウと対応
/// </summary>
[Connect]
public Window mainWindow;
#endregion
#region アクションの定義
// Export 属性でどのアクションと関連付けするか指定します
// 最後の: を忘れやすいので注意!
[Export("applicationWillFinishLaunching:")]
public void FinishLoading(object sender)
{
label1.Value = "Hello, Cocoa!";
}
[Export("buttonClick:")]
public void buttonClick(object sender)
{
label1.Value = "Hello from VisualStudio 2005!";
}
#endregion
/// <summary>
/// プロテクトコンストラクタ。
/// これがないと起動してくれません。
/// </summary>
protected ApplicationController(IntPtr nativeObject) : base(nativeObject) { }
}
}
これでビルドし、macpack すると、起動時にラベルが「Hello, Cocoa!」になり、ボタンを押すとラベルの内容が「Hello from VisualStudio 2005!」に変わるアプリケーションが出来ます。
*1 右ボタンがなければcontrolキーを押しながらクリック
*2 移動すると泣きをみます
*3 ビルド設定は Debug でも Release でもかまいません。どうせデバッグできませんし。ここでは Debug と仮定して説明をします。Releaseでビルドした方は以後そのように読み替えてください。
*4 Macintosh HD>Developer>Application に入ってます。
*5 セグメントって言うらしいけどこっちのほうがわかりやすいので
*6 保存したファイルを Windows から見るとフォルダとして見えます。
*7 Mac から Samba 共有に接続している場合は /Volumes に共有の名前でディレクトリができています。
*8 鉛筆マークついてる、アレ。僕は最初プロペラ押してました。
*9 この2つはチュートリアルに書いてあっただけで何故やるのかは理解していません。
Keyword(s):
References:[SideMenu] [技術ドキュメント]