C#
MacOSX
Xamarin

Xamarin.Forms.Platform.MacOS のはじめかた

Problem

Xamarin.Forms.Platform.MacOS が 2.4.0 リリースで Stable になっていたようです。
https://developer.xamarin.com/releases/xamarin-forms/xamarin-forms-2.4/2.4.0-stable/

当然IDEサポートはまだなので,Cocoa Appプロジェクトを作ったことがない方にもわかるように,作り方をまとめておきます。といっても Xamarin.Forms プロジェクトをブランクから作る方法と同じです。

Solution

プロジェクトを作る

ブランクのプロジェクトを適当に作りましょう。SharedでもPCLでもいいです。
Screen Shot 2017-12-19 at 1.25.26.png

すかさずCocoa Appプロジェクトを追加します。プロジェクト名を揃えてxxx.Macです。
Screen Shot 2017-12-19 at 1.34.48.png

Xamarin.Formsをインストールする

何はともあれ,NuGetからXamarin.Formsをインストールします。
Screen Shot 2017-12-19 at 1.37.53.png

Screen Shot 2017-12-19 at 1.38.43.png

ユーザーインタフェースの入っているSharedなりPCLプロジェクトを参照しておきます。
Screen Shot 2017-12-19 at 1.40.10.png

起動シーケンスを変更する

このまま実行するとMain.storyboardが読み込まれてウィンドウが構築されるので,これを抑止します。まずはMain.storyboardをすっぱり削除します。ViewController.csも要らないです。
Screen Shot 2017-12-19 at 1.44.01.png

Info.plistを開いてMain Interfaceをブランクにします。
Screen Shot 2017-12-19 at 1.45.07.png

AppDelegate.csを開いてusing Xamarin.Forms, using Xamarin.Forms.Platform.MacOSを追加し,NSApplicationDelegateの代わりにFormsApplicationDelegateを継承するようにします。

AppDelegate.cs
using AppKit;
using Foundation;
using Xamarin.Forms;
using Xamarin.Forms.Platform.MacOS;

namespace HelloForms.Mac
{
    [Register("AppDelegate")]
    public class AppDelegate : FormsApplicationDelegate
    {
        public AppDelegate()
        {
        }

        public override void DidFinishLaunching(NSNotification notification)
        {
            // Insert code here to initialize your application
        }

        public override void WillTerminate(NSNotification notification)
        {
            // Insert code here to tear down your application
        }
    }
}

FormsApplicationDelegateは abstract class なので,要求している実装を追加します。NSWindow型のMainWindowプロパティを実装しましょう。さらにAppDelegateコンストラクタから初期化しておきます。

AppDelegate.cs
public AppDelegate()
{
    var style = NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled;

    var rect = new CoreGraphics.CGRect(200, 200, 800, 600);
    this._window = new NSWindow(rect, style, NSBackingStore.Buffered, false)
    {
        Title = "Hello, Xamarin Forms!"
    };
}

private NSWindow _window;

public override NSWindow MainWindow => this._window;

DidFinishLaunchingメソッドで作ったウィンドウが表示されるようにします。

AppDelegate.cs
public override void DidFinishLaunching(NSNotification notification)
{
    Forms.Init();
    LoadApplication(new App());
    base.DidFinishLaunching(notification);
}

最後にMain.csを開いて,作ったFormsApplicationDelegateをアプリケーションに登録します。

Main.cs
using AppKit;

namespace HelloForms.Mac
{
    static class MainClass
    {
        static void Main(string[] args)
        {
            NSApplication.Init();
            // SharedApplication に触れるのは Init の後
            NSApplication.SharedApplication.Delegate = new AppDelegate();
            NSApplication.Main(args);
        }
    }
}

実行してみる

Screen Shot 2017-12-19 at 2.11.02.png

うまくいかないとき

  • Main.csで登録を忘れている
  • AppDelegate.csbase.DidFinishLaunching(notification); を書き忘れている

の実行時に起こりがちな2点以外は単にコンパイルエラーになると思うので適宜対処です。

Conclusion

このままではメインメニューがほとんど機能を持たないままなので,プログラムから作るなり,MainMenu.xibを作って追加するなり(see also:出た頃の記事)したほうがいいでしょう。
Cocoa App プロジェクトを追加し,Xamarin.Forms の起動シーケンスに乗っかるところまではこれでできるようになりました。.NET Standard化してみたり,カスタムレンダラーでmacOSの多彩なUI部品を使ってみたり,これを足がかりにトライしてみてください。