第3回:Xamarinにおけるコードの共通化とプラットフォーム固有のコードの記述:特集:Xamarin+Visual Studioで始めるiOS/Android/UWPアプリ開発(1/3 ページ)
Xamarin.Formsで提供されているコードを共通化する方法と、プラットフォーム固有のコードを書く方法を見ていこう。
Xamarin for Visual Studio(以降、「Xamarin VS」と略す)は、Visual Studioに統合されたクロスプラットフォーム開発環境だ。使い慣れたVisual StudioとC#で、クロスプラットフォーム開発ができる。この連載は、Xamarin VSを使ったアプリ開発の初歩を解説する。
クロスプラットフォーム開発の焦点は、どのようにコードを共通化して楽ができるかである。共通化率がゼロでは個別に開発しているのと同じで、クロスプラットフォーム開発とは呼べないだろう。そこで今回は、Xamarinでコードを共通化する方法について解説しよう。
コードの共通化
コードを共通化するというと、次の図のようなイメージが思い浮かぶだろう。プラットフォームごとのプロジェクトから、共通コードを利用するイメージだ。
このような共通コードを作る方法として、XamarinではPCL(移植可能ライブラリ)と共有プロジェクト(Shared Project)の2つが用意されている。前回まではPCLを使ってきたので、今回は後ほど共有プロジェクトの作り方を簡単に説明する。
共通コード内でプラットフォーム個別コード
上の図のようにきれいに共通コードを分離できないこともある。例えば、次の図のように、ほとんど共通の処理なのだが一部だけ(図では処理-C/C'/C")がプラットフォームごとに異なるといった場合だ。
プラットフォーム依存コードの前後で共通コードを分割してしまうと(上の図でいうと、共通処理-A/Bと共通処理-Dを別のメソッドにすると)、共通コードの見通しが悪くなってしまう。そのようなことは、できるだけ避けたいだろう。
この問題に対処するための仕組みを、Xamarinはたくさん提供している。後ほど詳しく解説していく。
1. PCLと共有プロジェクト
Xamarinで共通コードを使う仕組みには、PCL(移植可能ライブラリ)と共有プロジェクト(Shared Project)の2つがある。
PCL:
- 共通コードを独立したバイナリ(DLL)としてビルドする(バイナリレベルのコード共有)
- 他のアプリ開発にも転用しやすい(ロジックのみのPCLを作った場合)
- PCLのプロジェクト内部ではプラットフォームに依存するAPIは利用できない
共有プロジェクト:
- 共通コードをビルドするときに各プロジェクトに取り込む(ソースコードレベルのコード共有)
- 他のアプリ開発に転用するにはソースコードのコピー&ペーストになる
- プラットフォームに依存するAPIも利用できる(その方法は後述する)
PCLを使ったプロジェクト
前回作ったXamarin.Formsのコード(「Microsoft Developer Network > サンプル > Xamarin入門#02 HamburgerMenu」からダウンロード)で、PCLの特徴を見てみよう。
ソリューションエクスプローラーでPCLのプロジェクトを右クリックし、コンテキストメニューから[プロパティ]を選ぶと、プロジェクトのプロパティ画面が表示される。そこの[変更]ボタンをクリックすると、[ターゲットの変更]ダイアログが表示される(次の画像)。
PCLとは、この[ターゲットの変更]ダイアログでチェックの付いている全てのターゲットに共通のライブラリということである。逆にいえば、.NET FrameworkのAPIのうちで、チェックの付いている全てのターゲットで利用可能なものしかPCL内では利用できない。
次に、プロジェクトをビルドしてから、生成されたバイナリファイルを見てみよう。バイナリファイルは既定ではソリューションエクスプローラーに表示されていないが、上部の右から3番目のボタンで表示/非表示が切り替えられる(次の画像)。
生成されたバイナリファイルを見る(ソリューションエクスプローラー)
上のボタン(赤丸内)で、既定では非表示になっているファイルの表示/非表示を切り替えられる。
PCLをデバッグビルドした場合、プロジェクトの下の[bin]−[Debug]フォルダーにバイナリファイルが出力される(赤枠内)。
上の画像で、「HamburgerMenu.dll」ファイルが、PCLのバイナリファイルだ。PCLのソースコードをコンパイルしたものが、ここに入っているのである。
また、上の画像には、それ以外のバイナリファイルも見えている。「Xamarin.Forms.Core.dll」「Xamarin.Forms.Platform.dll」「Xamarin.Forms.Xaml.dll」の3ファイルである。これらは、PCLである「HamburgerMenu.dll」ファイルから利用されるXamarin.Formsのライブラリだ。ビルド時に自動的にここへコピーされている。
共有プロジェクトを使ったプロジェクト
共有プロジェクト(Shared Project)を使ったXamarin.Formsのプロジェクトを作ってみよう。
新しくソリューションを作るときに、[新しいプロジェクト]ダイアログで[Xamarin.Forms Shared]を選ぶ(次の画像)。
ビルドしてからソリューションエクスプローラーを見ると、次の画像のようになっている*1。
共有プロジェクトを使ったXamarin.Formsのプロジェクト(ソリューションエクスプローラー)
これまで作ってきたPCLのソリューションとプロジェクト構成はよく似ているが、生成されるバイナリファイルはずいぶんと違う。
一番上の「SharedPrj」プロジェクトが、共有プロジェクトだ。PCLで作ったXamarin.Formのソリューションと大体同じように見える。
しかし、生成されたバイナリファイルを見てほしい。「SharedPrj」プロジェクト内にバイナリファイルは生成されていない。「SharedPrj」プロジェクト内のソースコードは、ビルド時にそれぞれのプラットフォームのプロジェクトにマージされ、それからコンパイルされるのである。
UWP用のプロジェクトで説明すると、プロジェクトの[bin]−[x86]−[Debug]−[AppX]−[entrypoint]フォルダー*2にある「SharedPrj.UWP.exe」が、生成されたアプリ本体のバイナリファイルだ。この中に、「SharedPrj」プロジェクト内のコードをコンパイルした結果も含まれているのである。
*1 本稿執筆時点では、共有プロジェクトを使ったXamarin.Formsのプロジェクトは、自動生成されたままではUWPがビルドできなかった。[NuGetパッケージの管理]で、Xamarin.Formsのバージョンを他のプロジェクトと同じに合わせる必要があった(2.2.0.45)。
また、UWP/Windows 8.1/Windows Phone 8.1の3プロジェクトでは、共有プロジェクトに対する参照が設定されていなかった。そのままでもビルドはできるが、共有プロジェクト内でコードを書き換えた場合にはリビルドする必要があるようだ。共有プロジェクトに対する参照を追加しておいた方がよいだろう(それが本来の姿)。参照を追加するときの[参照マネージャー]で、左側の一覧から[共有プロジェクト]を選ぶと、共有プロジェクトへの参照を追加できる。
iOSプロジェクトのビルド時に「……(省略)……Default-568@2x.png does not exist」のようなエラーが発生することがある。簡単にこれを回避するには、iOSプロジェクトのプロパティページを開いて[iOS Build]タブにある[Optimize PNG images files for iOS]チェックボックスをオフにするとよい。Resourcesフォルダー以下のファイルが壊れているようであれば「Xamarinメモ その5 Xamarin.FormsでiOSがビルドできない」ページなどを参考にしてPNGファイルを入れ替えた方がよい。
*2 PCLプロジェクトの出力と比べて、複雑なディレクトリ構成になっている。これは、Windowsストアにアップロードするための「AppXパッケージ」という形式に対応するためである。
Copyright© Digital Advantage Corp. All Rights Reserved.