MVVMっぽくXamarin.Formsアプリ作ってみました。その4
続きです。
MVVMっぽくXamarin.Formsアプリ作ってみました。その1 - 眠いしお腹すいたし(´・ω・`)
MVVMっぽくXamarin.Formsアプリ作ってみました。その2 - 眠いしお腹すいたし(´・ω・`)
MVVMっぽくXamarin.Formsアプリ作ってみました。その3 - 眠いしお腹すいたし(´・ω・`)
コントローラインターフェースの実装
この画像の構成はPCLブロジェクトにて行われていますが、コントローラインターフェースの実装はPCLでは行っていません。
GitHub - yuka1984/XamarinFormsSampleStopWatch: Xamarin.Formsサンプルアプリ
今回のサンプルアプリではコントローラインターフェースはPCLプロジェクトのSwLib.Interfaceで作成していますが、インターフェースに対する実装はSwLib.Core、SwLib.Core.Droid、SwLib.Core.Touchで行っています。
SwLib.Coreは普通のクラスライブラリプロジェクト
SwLib.Core.DroidはAndroid用クラスライブラリプロジェクト
Swlib.Core.TouchはiOS用クラスライブラリプロジェクトになります。
これから説明する方法はUWPプロジェクトへの展開を意識していません。
あくまでもAndroidとiOSをターゲットとしたクラスライブラリの作成方法となります。
私は以下の手順でコントローラの実装を行っています。
- クラスライブラリプロジェクト(SwLib.Core)を作成してインターフェースを宣言しているPCL(SwLib.Interface)を参照設定する。
- インターフェースに対する実装クラスを作成する。
- 作成したクラスの単体テストSwLib.CoreTestsを作成して試験を行う。
- Androidクラスライブラリ(SwLib.Core.Droid)を作成してPCLを参照設定する。
- SwLib.Coreの.csファイルをリンクとしてSwLib.Core.Droidに追加する。
- iOSクラスライブラリ(SwLib.Core.Touch)を作成してPCLを参照設定する。
- SwLib.Coreの.csファイルをリンクとしてSwLib.Core.Touchに追加する。
SwLib.Coreの実装では普通のライブラリプロジェクトとAndroid、iOSのプロジェクトですべてファイルが一緒ですが、例えばコントローラインターフェースが複数あって一つのインターフェースに対してWindowsとiOSは共通だけどAndroidに関してはJavaを使って実装するなどという場合には、そのクラスの実装はリンク追加せずAndroidプロジェクトで実装を行います。
このような実装手順とプロジェクト構成はコントローラインターフェースだけでなく、共通化クラスにも適応します。
例としてKeyValueStoreというライブラリ実装を用意しました。
KeyValueStoreの実装
KeyValueStoreと言っていますが、簡易のデータ保存ストアです。
プロジェクト構成は
KeyValueStore.PCLはIKeyValueStoreというインターフェースを持っています。
KeyValueStore.CoreはIKeyValueStoreの.NET46用実装です。
KeyValueStore.Core.DroidはIKeyValueStoreのAndroid実装です。
KeyValueStore.Core.TouchはIKeyValueStoreのiOS実装です。
このライブラリはNuGet Gallery | SQLite.Net PCL 3.1.1を使用してIKeyValueStoreに対する実装を行っています。
Windowsクラスライブラリのファイルは3つ
XamarinFormsSampleStopWatch/Kvs.cs at master · yuka1984/XamarinFormsSampleStopWatch · GitHub
IKeyValueStoreに対するabstractの実装です。
各プラットフォームで差分がない部分を実装して差分をabstractとしています。
KeyValueStoreBaseのWindows用実装です。
Kvs.csとKeyValueStoreBaseはAndroid/iOSプロジェクトへリンク追加しますが、KeyValueStore.csはリンク追加せず、それぞれのプロジェクトで作成しています。
このプロジェクトではあまり実装に差分はありません。
DependencyInjectionを使用すれば吸収できる範囲だとは思います。
KeyValueStoreというプロジェクトを単独で切り離せる用にするために、このような形となっています。
今回のサンプルではXamarin.FormsプロジェクトとSwLib、KeyValueStoreを一つのソリューションで開発していますが、それぞれを別のソリューションで作成する事も可能な依存関係となっています。
ソリューションを分けた上でローカルnugetを使用した結合を行いXamarin.Formsアプリのソリューション自体を小さくすることができたりしますしロース管理のリポジトリを分けて開発することもできます。
今回は以上です。
次回、再度Xamarin.Formsプロジェクトに戻ってDIContainerに関して説明を行って終了にしたいと思います。
毎度細切れで申し訳ありません('ω')
Xamarin iOSのバインディングライブラリを組み込んだらエミュレータで動かせなかった
Xamarin iOSでネイティブのライブラリを使うためにバインディングライブラリを作ってプロジェクトに組み込んだりします。
作り方とかはこの辺を見たりします。
で組み込んでエミュレータで動かそうとビルドするわけですよ。エラーが発生するわけですよ。
アーキテクチャが対応してないよって。
.aファイルのサポートアーキテクチャがARMv7+ARM64だったりするわけで当然ですよね。
バインディングライブラリは参照に追加しているのでこのままではエミュレータで動かせなくなってしまう(´・ω・`)
Bindingライブラリを使っている機能は動かなくてよいからエミュレータで動作させたかったので以下のことをしました。
ちなみにバインディングライブラリは大体こんな感じで作ってます。
public abstract class HogeBase : IHoge { public static class NativeMethods { [DllImport("__Internal")] public static extern void Init(); [DllImport("__Internal")] public static extern void Start(); [DllImport("__Internal")] public static extern void Stop(); } public abstract void Start(); public abstract void Stop(); }
IHogeはAndroidとごにょごにょ・・・・
でXamarin iOSプロジェクトでは
public class Hoge : HogeBase { private static Lazy<Hoge> _instance = new Lazy<Hoge>(() => new Hoge()); public static Hoge GetInstance() => _instance.Value; private Hoge() { NativeMethods.Init(); } public override void Start() { Debug.WriteLine("start"); NativeMethods.Start(); } public override void Stop() { Debug.WriteLine("stop"); NativeMethods.Stop(); } }
こんな感じで実装していました。
構成がDebugでプラットフォームがIPhoneSimulatorの時に
__SIM__
というコンパイルシンボルを追加。こんな風に書き換えちゃう
#if __SIM__ public class Hoge : IHoge { private static Lazy<Hoge> _instance = new Lazy<Hoge>(() => new Hoge()); public static Hoge GetInstance() => _instance.Value; private Hoge() { } public void Start() { Debug.WriteLine("start"); } public void Stop() { Debug.WriteLine("stop"); } } #else public class Hoge : HogeBase { private static Lazy<Hoge> _instance = new Lazy<Hoge>(() => new Hoge()); public static Hoge GetInstance() => _instance.Value; private Hoge() { NativeMethods.Init(); } public override void Start() { Debug.WriteLine("start"); NativeMethods.Start(); } public override void Stop() { Debug.WriteLine("stop"); NativeMethods.Stop(); } } #endif
要するにIPhoneSimulatorで動かすときはバインディングライブラリを使わないっていうだけです。 参照でバインディングライブラリを追加していたとしても実際に使われなければビルドできます。
この問題ってどうやって解決すればよいか教えてください(´・ω・`)
MVVMっぽくXamarin.Formsアプリ作ってみました。その3
前回からの続きです。
MVVMっぽくXamarin.Formsアプリ作ってみました。その1 - 眠いしお腹すいたし(´・ω・`)
MVVMっぽくXamarin.Formsアプリ作ってみました。その2 - 眠いしお腹すいたし(´・ω・`)
ほんとに細切れでごめんなさい。
View
XAMLです。Bindingします。
ReactivePropertyをBindingすると時はProperty名.Valueとなるので注意です。
今回のサンプルでは作成していませんがUserControlを作ったりCutomRenderを作成したりする事は結構あります。
Xamarin.Forms2.1からはEffectsが追加されていますが試してないです。
WPFなどではIllustratorとかPhotoShopなどからXAMLを生成してコントロールを作ったりするのですが、Xamarin.Formsの見た目は絵を多めに使ったりしました。
View回りに関してはデザインとどのように連携するかなどのノウハウがもっとほしいなぁって思ってます。
Viewの機構的には色々と仕組みはありますが
あとはBehavior、WPFとかやってきてる人にはおなじみですよね。たぶん。
例えばボタンがクリックされた時にボタンのCommandプロパティにICommandをBindingしているとICommandがExecuteされます。
Xamarin.Formsでは無いですが、ボタンがマウスオーバーされたときにコマンドを実行したいような時にButtonを継承して新しいコントロールを作成するのでなくButtonにアタッチするような形でコマンドをバインドできる仕組みを作ることができたりもします。
またサンプルにはありませんがローカライズも正解がなくて悩みます。
前回も触れましたがページ遷移は悩みます。
実際の案件ではPageManagerクラスを作成してMessagingCenterで繋いで管理する形をとっていました。
PageManagerではコンテナーを使ってController、View、ViewModelのインスタンス管理とページ遷移を管理していました。
Navigation
Xamarin.Formsの基本的なページ遷移機構になります。
INavigation Interface - Xamarin
こんな感じのインターフェースを使ってページ遷移を行います。
NavigationはVisualElementクラスのプロパティです。
VisualElementを継承しているPageクラスはもちろんButtonにもNavigationはついています。
ある意味で広範囲からページ遷移を行うことができたりします。
ただNavigationをプログラムから呼び出さなくてもページ遷移を行うことができたりします。
それにはMultiPageを継承したPageを使います。
クラス関係はこちらのURLにある画像がわかりやすいです。
Introducing Calcium for Xamarin.Forms - CodeProject
MultiPageはabstractであり実装はCarouselPageとTabbedPageが用意されています。
この二つはIList
要するにChildrenにページをセットしておけば、それらのページ間の移動をUI操作に応じて勝手にやってくれるんです。
TabbedPageはタブでCarouselPage*1はスワイプでページ遷移を行うことができます。
イメージとしてはINavigationを使用したページ遷移はスタック・縦方向のページ遷移でMultiPageを使用したページ遷移は横方向のページ遷移になります。
XamarinFormsSampleStopWatch/App.cs at master · yuka1984/XamarinFormsSampleStopWatch · GitHub
今回のサンプルではStopwatchPageとSaveListPageはTabbedPageで横方向のページ遷移とし、SavePageへの移動はNavigationを使用して縦方向のページ遷移を行っています。
注意する点としてMultiPageのページ遷移は早いけどNavigationのページ遷移は早くないということがあります。
今回程度の画面であればほとんど気にならないレベルなのですがViewが複雑化したりBindingが増えたりするとNavigationにプッシュしたりした時の動作が重くなりユーザ操作がスムーズでなくなります。
この事はアプリを作るうえでユーザ体験をよくするためにも凄く大切なのでその辺を踏まえて設計を行ったほうが良いと思います。
今回はここまで。あんまりプログラムの解説してないですね(´・ω・`)
*1:CarouselPageは非推奨になるらしいです。
MVVMっぽくXamarin.Formsアプリ作ってみました。その2
前回
MVVMっぽくXamarin.Formsアプリ作ってみました。その1 - 眠いしお腹すいたし(´・ω・`)
の続きから
ViewModel
ViewModelですがINotifyPropertyChangedは実装しません。
ReactivePropertyを使用します。
コントローラの保持するモデルからReactiveProperty、ReactiveCollection、ObservableCollectionなどを作成します。
表示用のプロパティは基本的にReadOnlyReactivePropertyとしています。
入力用プロパティはReactivePropertyを使用します。
配列は基本的にReadOnlyReactivePropertyとしますが、必要であればObservableCollectionを作成します。
コマンドはReactiveCommandを使用します。
ReactiveCommandは他のReactivePropertyを元に実行可能状態を管理します。
ClearCommand = IsRuning.CombineLatest(elapsedtime, (run, t) => t > 0 && !run).ToReactiveCommand(); ClearCommand.Subscribe(x => { IsRuning.Value = false; IsStart.Value = false; stopWatchController.Clear(); });
コンストラクタでコントローラを受け取りReactivePropertyを作成していきます。
今回のサンプルではModelのプロパティは経過時間のmsecのlong値でしかないですが、それをRxで変形させてプロパティにしています。単純なlong値が時間フォーマット文字列に変形したり時計の針の角度に変形したりします。
Rotation = stopWatchController.StopWatchModel.ObserveProperty(x => x.ElapsedTime).Select(x => (double) (x/1000*6%360) - 90).ToReadOnlyReactiveProperty(); Time = stopWatchController.StopWatchModel.ObserveProperty(x => x.ElapsedTime).Select(x =>x.ToTimeFormat() + "->").ToReadOnlyReactiveProperty();
ロジックの結果であるModelは実体としてのデータであって表示のことは意識していないためコントローラの実装者はロジックの事に専念して実装を行うことができてUI担当者は実値を変形させることでUIを作成することができます。
ReactivePropertyを使用するとViewModelとロジック部をスッキリと分離することができとても良いです。当然Rxな書き方が可能となるためプロパティ同士の合成ができたり色々とつよいです。
ViewModelの再利用は考えていません。 ViewModelの再利用に関しては、過去いろいろ試したりしたけどうまくいったことがないので私の設計能力では無理だと思ってそれ以降考えたことはないです。
ViewModelの単体試験ですが、こちらも考えていません。 ただできないことはないかなぁと思ってます。 単体試験用のコントローラを注入してReactivePropertyのSubscriveにて値を記録するような形式でのテストが可能であると考えます。
ViewModelからのページ遷移
今回のサンプルではMessagingCenterを使用しています。
Publish and Subscribe with MessagingCenter - Xamarin
Appクラスのコンストラクタでページ遷移をSubscribeで実装しています。
XamarinFormsSampleStopWatch/App.cs at master · yuka1984/XamarinFormsSampleStopWatch · GitHub
ViewModelからSendしてページ遷移を呼び出します。
ToSaveCommand.Subscribe( x => MessagingCenter.Send(new NavigationMessage {IsModal = true}, NavigationMessage.ToSavePage));
正直、この実装はどうかな?って感じです。
もっと良い方法があれば知りたい感じです。
ページ間でのデータの受け渡しは必要に応じます。
今回のサンプルではロジック部の状態保持のみで実装可能であったためViewModel間での値の受け渡しは行っていませんが、例えばリストから詳細ページに移動するようなケースでは引数の受け渡しを行ったりします。
注意する点は画面遷移の為のデータ保持をコントローラで行ってはいけないということです。
今日はここまで。 ちょっとずつでごめんなさい。
MVVMっぽくXamarin.Formsアプリ作ってみました。その1
はじめに
世の中、すでにXamarin.Formsを使って作られたサンプルアプリはたくさんありますし、公式でもサンプルはあります。
私が今回作ってみたのはオレオレデザインパターンを適用して作ったアプリです。
Xamarin.Formsで一般的に使用されるデザインパターンはMVVMと呼ばれるものが多いのだと思います。
正直に申しまして、私自体MVVMって結局何なのだろう?っていう状況です。 私にとってはすごく難しいんです。 いろいろなサンプルを見るのですが各々結構違っていたりするんです。 マサカリが飛びまくっているんです。
Xamarin.Formsアプリを開発するにあたってどのようなデザインにするかすごく悩みました。
結局、MVVMはよくわからないから今ある知識でどうやったら今回の開発チームで効率よく開発できるか。
ということを考えてデザインパターンを設計することにしました。
- 少人数だけど分業して開発を行う必要がある。
- 機能ごと縦割ではなく、UIとロジックの横割で開発したい。
- UIとロジックは並行して開発したい。
- 最悪Xamarin.Forms無理ってなった時にもロジックは生かしたい。
この4つを意識して設計を行いました。
今後の勉強のためにも意見を頂けると助かります(ただし心が折れない程度に限る)
サンプルアプリ
今回作成したサンプルアプリケーションは
に公開をいたしました。
お題はJXUGであったストップウォッチアプリです。
ラップ機能付きストップウォッチ、結果保存、結果閲覧機能を実装しました。
kazukiさんの実装から劣化している感じになります"(-""-)"
すいません。iOSでテストしてません。WinPhoneは動きません。
デザイン
ばん(^^)/
こんな感じです。 すいません。こういう図を描くのが下手ですし説明なども下手です。 このBlogは私の復習とか説明練習も兼ねています。ほんとごめんなさい。
この図でいうControllerInterfaceの部分がロジック部になります。
そしてViewModelとView、MessagingCenterとNavigationがUI部になります。
概念の図なのですがライブラリ名とかクラス名が入ってしまっていますが今回の設計はそれらに依存している部分があるためです。
ControllerInterface
ロジッククラスのインターフェースです。
メソッドとModelInterfaceクラスをプロパティとして公開しています。
メソッドの呼び出しに対して結果をModelクラスに反映します。
またタイマーなどでの定周期処理に結果をModelクラスに反映したりします。
なぜインターフェースかというとViewModelを作る段階で実装ができていないからです。
開発の手順としては
最初にコントローラインターフェースおよびモデルインターフェースの設計を行い作成をします。
ロジック担当者はインターフェースに対する実装を別プロジェクトにて作成します。(サンプルではSwLib.Coreというプロジェクトにて実装してます。)
UI担当者はインターフェースに対するモッククラスを作成しながらViewModelを作成していきます。
ModelInterface
モデルクラスはINotifyPropertyChangedを実装しているのでプロパティの変更を監視できます。
プロパティはReadOnlyのみで定義し外部からの変更を受け付けません。
配列型の場合にはReadOnlyObservableCollectionにて実装されているので変更を監視できます。
配列型も外部からの変更を受け付けません。
なぜモデルまでインターフェースになっているかなのですがINotifyPropertyChangedの実装をどうするか決めていなかったからです。
なぜ公開しているプロパティがすべてReadOnlyかというとUI部側から勝手に変更されるように事を避けたかったからです。開発初期段階でチーム参加者がデザインパターンに不慣れだったこともあって意図しない実装を設計的に防げればなぁという感じでした。
今回はここまでで、また続き書きます。
C#でRakuten MA使って形態素解析してみた。
夜遅くにツイッターみてたらフォローさせていただいてる絵空事さんがこんなのツイートしてました。
Rakuten MAってなに?
ってことでちょっと調べてみました。
JavaScriptの形態素解析をするライブラリみたいです。
この手の分野は全然疎くて.NETで形態素解析っていうとNMeCabなぁってことくらいしか知りませんでした。
このライブラリはブラウザ上かnode.jsがあれば実行できるって言う事が分かりましたが
そういえばJavaScriptをC#上から実行ってできないのかな?
ってふと思いました。
javascript C# 実行 なんてキーワードで検索したらASP.NETに関する結果ばかりヒットしてしまいました。
検索を進めると
こんな記事を発見(*'▽')
node.jsとEdge.jsの間の接続はシームレスで双方向である
(; ・`д・´)
C#からnode.jsの環境で実行可能ならRakutenMA使えるんじゃない?
ってことでEdge.jsについて調べてみました。
日本語でヒットしたのはこれくらい
これ、確実にRakutenMA実行できるじゃん(*'▽')
っていうことでとりあえず実行できるようにしてみました。
めんどくさいのでスクショばん(≧◇≦)
やったことはとりあえず
- コンソールプロジェクト作る
- Edge.jsとNewtonwoft.Jsonをnugetより追加
- RakutenMAをgithubより取得してプロジェクトに追加
- ファイルを全部ビルドアクション:なし 出力:常にコピーするに変更
- プログラム書く
- つまづく
- 結果これ
すばらしい(*'▽')
プログラムは
ここを参考にしました。
jsコードはdemo.jsから抜粋
つまづいた点はrequireのパスとfsのファイルパスでrequireのパスはとfsのCurrentが違っていてアレ?ってつまづきました。
C#からJavaScriptが実行できて結果を受け取れちゃう世の中です。
凄い世の中です。
RakutenMAだけじゃなくて色んな事に応用できそうですねぇ。
以上
Xamarin.Forms開発で必要な知識
Build以降のXamarin界隈が活気がすごいです。
前はここまですごくなかったのに急にどば~~(; ・`д・´)って感じです。
Xamarin.Formsでの開発に関しての所感は以前書きましたがTwitterのTL見ていて知識面に関してちょっと書いてみようかなと思いました。
あくまでも私自身が感じた感想みたいなものですし、作るものによっても変わってくるとは思いますし、規模によって個人が必要な知識の範囲も変わるので参考程度にお願いします。
開始時の知識・経験
Xamarin.Formsでの開発を始めた時点での私は
という状況で開発をスタートしました。
主に二人で開発をしていますが、もう一人の方はiOS開発の経験があるけど逆にWPFやAndroidに関しては経験ない感じでした。
開発での役割としてプログラムデザインは私が全て行いました。
私自身は東京さとおくて勉強会とか出たことないレベルのプログラマです。
開発時点で必要だと思った知識
Xamarin
Xamarinというものへの理解は必要です。C#/F#で書いたプログラムがどのように各プラットフォームで実行されるのか、イメージだけでもつかんでおく必要があります。
とはいっても
この資料を読んでわかるくらいで良いと思います。
これ、とても分かりやすいです。
www.slideshare.net
Xamarin.Forms
Xamarinを理解したうえで、Xamarin.Formsがクロスプラットフォーム開発のどの範囲をカヴァーしてくれるか理解しておくと良いと思います。
感覚的にXamarin.Formsが何をしているかも知っておいた方が便利です。
これを理解していないとプログラムデザインを行うことがとても難しいです。
www.slideshare.net
バインディングスタイルでの実装
これはコードビハインドで作る事もできるので必須ではないですがXamarin.Formsでの開発のメリットを出すためには必要だと思います。
バインディングスタイルのデザインに関する知識はできれば欲しいかなと思います。
を追っておけば間違いないと思いますが私には難しかったりします。
www.slideshare.net
XAMLの知識は重要ではないと思っています。開発していれば覚えます。 ただしXAMLが各プロットフォームのネイティブなUIに変換されて実行される点は知っておく必要があります。WPFのXAMLとは異なる点です。
PCL/Shared
プロジェクトの種類にてPCLとはどういうものか、Sharedとはどういうものか、理解しておく必要があったと思います。
あまりよくわからない状態で選択すると後で(´・ω・`)な顔になったりします。
プログラムデザイン、プロジェクト構成にも大きく影響します。
開発中に必要になって勉強した知識
C# async/await
私自身があまり理解できていなかったので勉強しました。
C# ReactiveExtentions
開発にてViewModel層にReactivePropertyを導入したのでRxを生かすために勉強しました。
各プラットフォームのネイティブ実装
次のプッシュ通知もそうですが、各プラットフォーム毎にプログラムを作らなければならない部分に関しては、そのプラットフォームでの実装を参考にします。
Objective-C Swift Javaのソースコードを読むことになります。
各プラットフォーム毎の違いを抽象化してPCLで扱えるように考える作業もあります。
プッシュ通知
開発にてプッシュ通知を実装する必要があったため
- 各プラットフォームでのプッシュ通知の特性の違い
- 各プラットフォームでのプッシュ通知の実装
- どのように抽象化してPCLプロジェクトで扱うか
などを、勉強したり考えたりしました。
この辺はXamarinとか関係なく、各プラットフォームでの記事を読みまくりました。
プッシュ通知関連のバックエンドに関しても全て私が作っているので送信側もそれなりに勉強しました。
ディープリンク
アプリは普通はアイコンをタップして起動するものですがWebページから起動するようなケースもあるかと思います。 そういう実装の場合、アプリがインストールされていなかったら~~な動作とか、いろいろと考える必要があります。いわゆるDeepLinkと言われるものです。 プラットフォーム毎にけっこう異なるのとiOSは8/9/9.1/9.2で全然動きが異なっていたりで苦労しています。
Xamarin.Forms
開発中にもバージョンアップが行われ新しい機能が追加されたり変化していきます。
また
なんか挙動がおかしい、Navigationをカスタマイズしたい、これどうやったら実現できるのか
等々いろいろ出てきますので、都度勉強しました。
NDKとObjective-Cでの共通化
CコードのNDK、Objective-Cでの実装部分があったため知識が必要でしたが、私が担当でないため結果だけしか聞いていないです。
通常はあまり必要ないかなと思います。
Xamarinからの呼び出しはP/Invokeで簡単です。
デプロイと運用
世の中に公開する前段階・公開後のバージョンアップと運用なども勉強するがありました。
この辺は役割として私が主担当ではなかったので調査結果を聞くだけでしたが開発チームとしては勉強しました。
- Google Playへの登録
- AppStoreへの登録
- 各プラットフォーム毎のベータテストの公開と運用方法
- クラッシュレポート
- 各プラットフォームでの強制アップデート
等々ですね。
所感
Xamarin.Formsを使えば全てが共通化できるなんて幻想は存在しません。
各プラットフォーム毎の知識は必要になります。
が、調べれば何とかなる範囲の事が多いと思います。
Android/iOS開発のスペシャリストがいなければ開発なんてできない。
なんてことはありません。
インターネットには色々と各プラットフォームの解決策が載っています、
Xamarin.Forms自体の情報はそれほど多くはありませんが、プラットフォーム毎の解決策が分かれば乗り越えられます。
私自身はもうすぐ仕事での開発が終わってしまうのでXamarinに触れる機会は減ると思います。
6月以降、諸事情にて会社を休職する事になっているため、開発の真っただ中からしばらく離れます。
Xamarinで開発始めたのが去年の夏前くらいからでしたが、出来れば今年のそれくらいの時期から開発始めたかったなぁと思っています。
いま、去年の比じゃないくらいXamarinが注目されています。
モバイルのクロスプラットフォーム開発始めるならXamarinで今すぐ始めよう。
以上