Xamarin.Forms でも HotReload がしたい！

こんにちわ。
過去5年で9個!のアドベントカレンダーをこなして来た Xamarin、過渡期における認知・普及に大いに貢献できたと思います、参加頂いた皆様に改めてお礼申し上げまする。
Xamarin が成熟期に入ったであろう今年は「そろそろ頃合いかな[^1]」とホストもせず放置していましたが、@muak_x さんが立ち上げられたので「ならば協力せねば」という事で、埋まりづらいであろうトリに名乗りを上げさせて頂きました。しかしその後の様子を見るにそれも杞憂だったかな、と。皆様の Xamarin に対する意欲の高さを感じることができました。

[^1]: 個人としては趣味でも興味でもまだまだ全然Hotなんですよ、Xamarin「も」

さて前置きはこのくらいで、、、、
画面の開発（画面レイアウト作成）をする際、みなさんが好む「スタイル」は何ですか？

 * デザイナーでポチポチ
 * xml や xaml などの DSL を手書き
 * DSL も使わん、全部プログラム言語で手書き
 * etc
 
私は 「xml や xaml などの DSL を手書き」 派です。

いずれにしても「UIの見た目」を逐次確認しながら開発できるというのは、画面開発においては必須要件です。
この 「見た目を確認する機能」 は、プラットフォームや IDE によっていくつかの提供方式があります。

## UIデザイナ vs プレビューア vs HotReload

UIデザイナとはアプリ開発環境でいうと「UI部品をドラッグ&ドロップでレイアウトできる」機能を差します。多くの場合はそれが「プレビューア」も兼ねています。

プレビューアとは、コードで記述されたUI定義の「見た目」を「シミュレート」する機能です。

HotReload とは、「実際のアプリケーション」を動かしながらも、コードやUI定義の変更を即座に実際のアプリケーションに反映させる機能を言うものとします。

それぞれのメリットデメリットを考えて挙げてみました。（個人の恣意的な見解を大いに含みます。）


### UIデザイナ

- ⭕ - 初心者に「使いやすい」と思わせることができる
- ❌ - 生成されるUI定義コードが人間には理解不能(and diff unfriendly)
- ❌ - (IDE提供会社側)機能を作るのが超大変・面倒

UIデザイナを採用するのは Visual Basic 6, Windows Forms, WPF/UWP/ASP.NET(Web Forms)/Xamarin Native(Android/iOS) など、macOS/iOSアプリ開発の Xcode(Interface Builder/Storyboard)、Android Studio の UI Editor、アプリ開発以外では Word やホームページビルダーなどもそうですね（これらを挙げるのは恣意的ですがw）。

## プレビューア

- ⭕ - (自力で)視認性の高いコードを記述できる(ツールに邪魔されない)
- ⭕ - 任意のタイミングあるいはリアルタイムに、見た目を「おおよそ」確認できる
- ❌ - (IDE提供会社側)異なるプラットフォームの「見た目」を再現しようとすると、実装が大変・面倒

プレビューアを採用するのは、Visual Studio 20xx の XAML Previewer for Xamarin.Forms くらいですかね。GitHub や Qiita などに見られる「Markdown のリアルタイムプレビュー」も該当すると言えるかも知れません。

## HotReload

- ⭕ - (自力で)視認性の高いコードを記述できる(ツールに邪魔されない)
- ⭕ - 実際のアプリケーションを動かしながら、見た目の変更を「完全に」確認できる
- ❌ - (IDE提供会社側)アプリ側にIDEからの変更通知を受信するための「仕掛け」が必要

HotReload は、最近では Flutter が名を上げていますね。React や Angular でも細かい方式の違いはあるのでしょうが、デベロッパー体験としては HotReload のような事ができます。Android Studio の「Instant Run」もここに分類することにしましょう。

## どれがいいの？

改めて個人の見解ですが、ここで言いたいのは
**「UIデザイナーやプレビューアはそれを提供する側の開発コストがとても高いが、その割にそれを利用する側の評価は低い（見た目が実際と<少し>違う、等）」**
と言うことです。[^2]

[^2]: まあ「UIデザイナ やプレビュー機能はもう二度と作りたくない」という過去の体験からくる意見です

対して本物のアプリを動かしつつUIを変更できる HotReload は、
**「(UIデザイナに比べて)提供側の開発コストは低く、利用する側の開発体験は高い」**
と思います。「デベロッパー目線では」 HotReload はとってもコスパが高いと思うんですね。

Microsoft は、Visual Studio で Xamarin.Forms アプリの HotReload が可能になるはずだった 「 [Xamarin LiveReload の開発を停止し、プレビューアの機能を強化していく](https://github.com/MicrosoftDocs/xamarin-docs/issues/947#issuecomment-432973028) 」そうですが、私にはこれは悪手に見えます。
開発環境も実行環境も Windows だった WinForms/WPF に対して、異なるプラットフォーム上で動作するアプリケーションの見た目を Windows の IDE上で再現(プレビュー)する事は、相当な開発コストが必要と推測します。
それだけのコストをかけても「Windows 上で表示されるプレビュー」は所詮 **ニセモノ** であり、その再現性に私は期待が持てないのです。GoogleMapsを埋め込んだユーザーコントロールを開発してる身としては「どう考えてもムリ」という結論になります。

Xamarin LiveReload は Visual Studio for Macでいつ使えるようになるのかなー？と言う期待は、遂に実現されませんでした。

もう一つ、 [Xamarin Live Player](https://docs.microsoft.com/ja-jp/xamarin/tools/live-player) というものがありました（もう過去形でよいと思ってるけど）。
これは実機に「開発中アプリを実行するためのアプリ」をインストールしておき、それが開発中アプリのコードを解釈＆実行することで HotReload が可能です。しかし [iOS版アプリがAppStoreから削除され、testflightでの公開もなくなり、今はAndroid版のみの提供となっているよう](https://www.sys-cube.co.jp/blog/15002.html) です。そして活発な開発は行われていないように見えます。

Microsoft には「初心者にウケのよい機能にチカラを入れる」という SAGA があるように感じますが、それが徒にならないとよいですなと願います。（注力するのは良いんですが、それによって全体のDX(Developer Experience)を下げるのはよろしくない選択だと思います。）

## LiveXAML なら Xamarin.Forms で HotReload ができるんじゃぁぁあいッ！！

よろしい、Visual Studio の標準機能としてそれが搭載されることは諦めましょう。
VS に頼らなくても、我々には素晴らしいツールを提供してくれるサードパーティーがいます。

**[LiveXAML for Xamarin.Forms](https://www.livexaml.com/)** は livexaml.com で販売・配布されている拡張ツールです。

* IDE(Visual Studio 201x、Visual Studio for Mac)のエクステンション
* アプリに入れる nuget パッケージ

から成っています。

開発・提供者はちょっと辿りにくいのですけど、「ION OÜ」というエストニアの屋号が確認できました（が、規模はおそらく小さいでしょう）。他に [ammyui](http://www.ammyui.com/) という、「XAMLの代わりにJSONライクな定義でUIを記述できるツールキット」も開発しているようです。

### LiveXAML のインストール方法

Visual Studio for Mac で使ってみます。Win の人は [INSTRUCTIONS](https://marketplace.visualstudio.com/items?itemName=ionoy.XamarinFormsLive-18843) を見てね。

#### 1. Visual Studio for Mac に LiveXAML の Extension を入れる

Visual Studio for Mac を起動し、左上のアイコンから Extensions... を選択、Extension Manager の検索ボックスに "LiveXAML" と入力し、インストールします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/8227/0c35f9b0-2b33-55c6-775a-6362b4576e1a.png)

インストール後、Visual Studio を再起動したほうが良さそうです。

#### 2. アプリケーションのプロジェクトに LiveXAML の nuget パッケージを入れる

Xamarin.Forms の共通プロジェクト（.NET Standard） **のみ** に、 LiveXAML nuget パッケージを入れます。
（間違えて Android プロジェクトにも入れたところ、ビルドエラーになりました）

例として拙作 Xamarin.Forms.GoogleMaps のサンプルアプリソリューションを挙げると、 ``XFGoogleMapsSample`` プロジェクトのみに LiveXAML を入れます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/8227/e07401f2-db44-6434-b718-c4016e79d8c1.png)

#### 3. 動かしてみる

Trial するためのステップはこれで終わりです。

##### エミュレータで実行

試しに Android エミュレータでアプリを **デバッグ実行** し、そのまま画面の ``.xaml`` ファイルを Visual Studio で変更し、保存すると、数秒以内に実行中のアプリに適用されます。

![Untitled6.gif](https://qiita-image-store.s3.amazonaws.com/0/8227/110415b8-ed63-d922-f04f-43b6e9f7df77.gif)

もちろん iOS でもおｋ。

![Untitled7.gif](https://qiita-image-store.s3.amazonaws.com/0/8227/076bb2db-5113-ad04-dbdd-3cea88bf592f.gif)

UWP に興味が無いのでまったく触れていないですが、LiveXAML は UWP にも対応しています。

##### 実機で実行

Android, iOS ともに開発PCと「同じネットワークに接続されている」ならば、実機でも HotReload されます。

iOS の方は、ビルド設定で Linker の動作 を 「Don't Link」 に変更する必要があるかもしれません。既定で 「Don't Link」 ならOKです。（Link All, Link Framework SDK Only では動作しません。）

##### デバッグじゃなくても HotReload

"Update even if not debugging" というオプションを ✔ すれば、デバッグ実行でなくても適用されるそうです(VS4M にその項目はなかったので VSforWinならあると思われ)。

これにより、Rider などの外部エディタでの変更も適用できたり、複数の端末に適用させることもできるとのことです。前出の FAQ より。
うまく使うと、 **Android アプリと iOS アプリを同時実行しながら、HotReload できる** んじゃないかな？(要確認)


どうっすか。これですよ私が求めていた開発体験(DX: Developer Experience)は！

### LiveXAML でできないこと

#### XAML ファイル以外の変更適用

"HotReload" されるのは ``.xaml`` ファイルへの変更のみです。
``.cs`` ファイルを変更して保存しても何も起こらないし、``.cproj`` への変更も反映されません。
例えば ``<Image Source="apple.jpg" />`` とXAMLに書かれた時に、 ``apple.jpg`` をりんごからオレンジの画像に差し替えても、りんごのままです。

あれ、あんまり「できない事」はなかったｗ 詳しくは https://www.livexaml.com/ の FAQ を見てください。

ちなみに C# ソースコードの変更を HotReload する技術? も開発中で、

* LiveSharp - https://github.com/OYIon/LiveSharp

というそうです。Windows + Visual Studio なら試せるらしいので、興味ある方はどうぞ。

### トラブルシューティング

今のところ、

* VS4M に LiveXAML Extension をインストールしてすぐアプリ実行したが HotReload されない → VS4M を再起動したらなんか大丈夫になった
* LiveXAML nuget パッケージをコアプロジェクト以外には入れる必要がないのに入れちゃった → ビルドエラーになった
* iOS アプリで HotReload されない → Linker が Link Framework SDK Only になってた(Don't Link にする必要がある)

に遭遇しました。いずれも VS4M の Application Output にログが出力されるので、それを手がかりに調べれば、なんやかんやで解決するでしょう。

### 買うよね？

そんな LiveXAML、価格は

* $24 / 月
* **$240** / ∞

です。年間240$ じゃないよ **「無制限」** だよ。
即買いだよね。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/8227/4741eebd-a9c9-9904-f2ae-dd9363e730c0.png)

はい買った。感覚的には Donation です。

## まとめ

「世はまさに大HotReload時代」だけど Xamarin.Forms ではできるの？」
↓
**「Visual Studio だけではムリ。でも LiveXAML という拡張機能を使うとできるよ！」**
↓
「なるほど、値段も **$240 ポッキリだから、これは「その成果に敬意を表する寄付」だと思えば安いもの** だね！」
↓
「Exactly！ こうして Visual Studio に頼らない開発ツールが増えていくと、開発者の選択肢が増えて、まさに "Any Developer, Any App, Any Platform, **Any Tool**" だね！」