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でもいいです。
<img width="618" alt="Screen Shot 2017-12-19 at 1.25.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/34563/81827d53-628b-27bc-130b-01852c0b00c2.png">

すかさずCocoa Appプロジェクトを追加します。プロジェクト名を揃えて`xxx.Mac`です。
<img width="1158" alt="Screen Shot 2017-12-19 at 1.34.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/34563/bf069c87-615b-c3ce-dee3-59972195be20.png">

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

何はともあれ，NuGetからXamarin.Formsをインストールします。
<img width="295" alt="Screen Shot 2017-12-19 at 1.37.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/34563/9e39c9fb-b282-03aa-21da-c2692d95d717.png">

<img width="1122" alt="Screen Shot 2017-12-19 at 1.38.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/34563/ef1db340-885d-191f-b9f8-dc9251126754.png">

ユーザーインタフェースの入っているSharedなりPCLプロジェクトを参照しておきます。
<img width="845" alt="Screen Shot 2017-12-19 at 1.40.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/34563/75a1a899-ba46-06c9-d36b-bf3b664522e6.png">

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

このまま実行すると`Main.storyboard`が読み込まれてウィンドウが構築されるので，これを抑止します。まずは`Main.storyboard`をすっぱり削除します。`ViewController.cs`も要らないです。
<img width="386" alt="Screen Shot 2017-12-19 at 1.44.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/34563/2b23bff9-43d9-a328-2a3d-961349996a13.png">

`Info.plist`を開いて`Main Interface`をブランクにします。
<img width="1071" alt="Screen Shot 2017-12-19 at 1.45.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/34563/f2ca56a9-8788-7176-b321-121668a7cf53.png">

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

```csharp: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`コンストラクタから初期化しておきます。

```csharp: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`メソッドで作ったウィンドウが表示されるようにします。

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

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

```csharp: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);
        }
    }
}
```

## 実行してみる
<img width="855" alt="Screen Shot 2017-12-19 at 2.11.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/34563/b6db84d7-fae6-c6fc-86aa-cafdd9301fcf.png">

## うまくいかないとき

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

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

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