[WIP] Xamarin.iOS アプリ開発の全体像

この記事は 「初心者歓迎XamarinのLT会!Xamarin入門者の集い #4」の発表補足資料です。

私のググる能力が低いだけかもしれませんが Xamarin.Forms での記事や事例報告、スライドに比べて、Xamarin.iOS を使ったという日本語レポートがとても少ない気がするので、特に Swift や Objective-C で iOS や macOS アプリを書かれている方に向けて、初めての一歩からリリースまでのざっくりとした全体の雰囲気についてお伝えします。

0. 取り巻く環境を選定しよう

 iOS アプリを作ることになった場合、開発者に経験がなければ Swift, Objective-C で開発することが一番堅実な選択肢だと思います。iOS アプリに限った話ではないですが、得てしてフロントエンドというものはデバイス依存の問題、OS の問題、要因のよくわからない問題など、開発する上で様々な問題が生じます。一番情報量が多いという点と、オフィシャルであるという点で、やはり経験のない方は Swift, Objective-C を選ぶと良いでしょう。

 すでに経験をお持ちの方には、個人的には Xamarin.iOS も選択肢のひとつとしてお勧めできると考えています。また、スタートアップなどでは ReactNative も実際に製品で利用されているケースを頻繁に目にします。また、クロスプラットフォーム開発という点においては Xamarin.Forms も有力な選択肢かと思います。

 このような選択肢のなかからどれを選ぶべきか。答えは決して一つではないと思いますが、私の考えではその開発において、アプリユーザーに一番価値を提供できる環境を選ぶのが妥当ではないかなともっともらしいことを言っておきます。

 小さいアプリでそれほど複雑なことをやらず Android と iOS を素早く作ってリリースしたいと言った場合、どの環境を選んでも、特段差し支えない程度にどれも一長一短あります。JavaScript が得意な方であれば、実はクイックさという点では ReactNative という選択肢もかなり有力なのではないかと思いますが、私自身は ReactNative でのストアアプリリリース経験は残念ながらないため、断言はできません。

ライブラリも含めてコードの枯らして安定した稼働を狙いたい場合や、機能追加に多くの時間をさきたいと言った場合、意外にも Objective-C や、言語として枯れている C# を利用する Xamarin.iOS を選択するのも一つの選択肢になるのではないでしょうか。

 あるいは王道を行き冒険せずに素直に作る場合や、既存の資産を生かしたい場合は Swift で開発するのが妥当でしょう。まあ普通に考えれば Swift を使うのが一番無難です。

 以上のようなことを鑑みて、どれを使うのがよいか皆様の価値観の軸を基準に選定してみてください。

1. Xamarin.iOS(C#) と Swift: 言語の違い

注: この節は現在書きかけです。雑な記述となっている点ご容赦いただければと思います。

環境の選定をする上で、それぞれの違いをそれなりに知っている必要があると思います。ここではまず、Swift と C# の言語という側面から、実際の開発に影響してくる違いをご説明します。

1.1. エディタ

個人の感想をあまり書きすぎるのはフェアじゃないのですが、この項目はどうしても個人の感想によってしまいますね。Visual Studio は快適です。

  • C# では Visual Studio for Mac という強力な IDE が利用可能
    • 個人的にはかなり快適にプログラミングできる良い統合開発環境だと思います
    • C#, Java は冗長という点で叩かれやすい言語ですが、実際そんなに文字数打たない(無駄に長いコードは読み手のコストを削るので、冗長なのはその点ではよくないとは思いますが、書くのが大変という意見にはクエスチョンマークが付く気がします)
    • 会社で業務つかうときにはライセンス契約が必要です
  • Swift では Xcode
    • 徐々に改善はしている(一時は変数のリネームとかできない状況でした)
    • AppCode を使うという手もあるが最近の Swift への対応状況追えていない(有識者〜)

1.2. 依存ライブラリの利用

 基本的には C# のライブラリを利用することになります。 nuget という CocoaPods に相当するライブラリ管理システムがあり、Visual Studio に統合されているため、 GUI で簡単にライブラリの追加やアップデートが可能です。

 Swift や Objective-C のライブラリを利用したい場合はネイティブバインディングを行うコードを記述しなければいけない点が面倒ではあります。要件的にこれらのライブラリを多く用いるような案件には向いていないことは確かです。ネイティブバインディングについての詳細は 公式ドキュメント をご覧ください。

1.3. Optional(Swift), Nullable(C#)

  • Swift では class/struct 問わず Optional が利用できます
  • C# 7.0 まででは値型(struct) にしか Optional は利用できません
    • C# 8.0 からは参照型の Optional が利用できます #

現状は Swift の Optional のほうが扱いやすいというのが私の意見です。

1.4. 例外

  • Swift 2 より例外が導入された
  • C# はおおよそ Java などと同じ感覚で例外をハンドリング可能

1.5. 名前空間(C#)

  • C# には扱いやすい名前空間が存在している
  • Swift ではプロジェクト分割により似たようなことが可能だが、現実的には namespace より柔軟さに欠ける

 現実的によほど大きな iOS アプリでない限り、細かく名前空間をコントロールする必要性はそこまで生じません。しかし、設計の観点から不要なものにはアクセスできないようにしておくことは、コードがどこから参照されて欲しいのかという意志を表現できたり、機能追加時に他の開発者がおかしな依存関係を作ってしまうことを防げたりできて、良いことだと思います。

1.6. アクセスコントロール(Swift), アクセシビリティ(C#)

1.7. async/await

  • C# では async/await を用いて、非同期処理の同期的な記述が可能
  • Swift でも近い将来のアップデートで言語にフィットする形で導入される予定 #
    • 安定化とライブラリ側の対応を考えると現実的には少し先の将来となるかとは思います

1.8. 定数と変数、型推論

  • Swift の let のほうが便利だと感じる
    • C# で対応するものは const, readonly あたりだが let とは本質的に異なる機能もあり単純な対応関係ではない
  • 感覚的で申し訳ないですが、C# のほうが型推論に対して安定感を感じます(エディタの振る舞いのせいかも)

1.9. クロージャ(Swift), ラムダ式(C#)

ここも好みの問題ですが、C# のラムダ式のほうが一般的な記法で馴染みがあるという感覚程度の感想でしかない

1.10. abstract class(C#)

  • C# にはインスタンス化をさせない抽象クラスのマークとして abstract キーワードが利用できる
    • ちょっと規模が大きくて複雑な設計をする際に、どうしても使いたくなるケースはあると思うが、基本的には継承を避ける方向で最大限対応したい

1.11. (余談) protocol と interface

  • C# では interface が型パラメータを持てる
    • これについては、どちらかというとライブラリ層を書く人に影響が大きいかなと思う違い
    • アプリ開発のレイヤーで差はあまりでないと考えてよい
    • アプリ開発する上で、この点が大きく効いてくるとしたら設計ミスの可能性も大きそう

2. Xamarin.iOS(C#) と Swift: 同じ点

Xamarin.iOS にしろ Swift にしろ、あまり開発する上でかわらない点のうち、個人的には大きなポイントだなという部分をいくつかご紹介します。

2.1. UIKit の取り扱い

  • Swift の API がそのまま C# の命名規則に移植されただけと考えて差し支えないレベルで、ほぼ1対1対応している
  • 実際にコードの一例を見るとわかりやすい

Swift のコード

import UIKit
import CoreGraphics

class MainViewController: UIViewController {

    let button: UIButton = UIButton()

    override func viewDidLoad() {
        super.viewDidLoad()
        button.setTitle("gochiusa", for: .normal)
        view.addSubview(button)
    }

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        button.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
    }
}

C# のコード

using UIKit;
using CoreGraphics;

namespace Your.Name.Space
{
    class MainViewController : UIViewController
    {
        readonly UIButton button = new UIButton(UIButtonType.Custom);

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            button.SetTitle("gochiusa", UIControlState.Normal);
            View.AddSubview(button);
        }

        public override void ViewDidLayoutSubviews()
        {
            base.ViewDidLayoutSubviews();
            button.Frame = new CGRect(0, 0, 100, 100);
        }
    }
}

2.2. Storyboard/Xib の取り扱い

 Xamarin.iOS を使った場合でも Swift/Xcode での開発同様、ストーリーボードや Xib を用いることができます。Visual Studio for mac 上で直接編集することができるほか、物自体は同じなので Xcode で編集することもできます。詳しくは 公式ドキュメント をご覧ください。

2.3. Assets Catalog の利用

 画像の取り扱いも基本的には Xcode で開発していたときと同様に Assets Catalog を利用することができます。詳しくは 公式ドキュメント をご覧ください。

2.4. plist の利用

 plist に関しても Xcode で開発していたときと同様に使うことができます。Info.plist については Visual Studio 上にも GUI で編集ができるので、感覚としては全く変わらずに開発できると思います。公式ドキュメント はこちらです。

2.5. 多言語化対応

 iOS 開発者にはおなじみの Localization の仕組みがそのまま使えます。詳細は 公式ドキュメント をご覧ください。

3. Xamarin.iOS 開発を取り巻く環境

3.1. CI/CD

 NUnitを利用したユニットテストの実行は Bitrise を用いると簡単に実現できます。基本的にウィザードに従い、GitHub リポジトリとの連携をかけるだけで、テストやアーカイブ、ベータ配信などを自動化できます。

 たとえば、純粋な .NET のプロジェクトとそれに依存する Xamarin.iOS プロジェクトを持つようなソリューションの CI の実現例として Xamarin.iOS.NonStoryboard を作りましたので、フォークなどをしてお試しいただければと思います。

3.2. GoogleAnalytics を用いたアクセス解析

 GoogleAnalyticsは、一般的な iOS アプリ開発同様、簡単に導入することができます。 nuget から Xamarin.Google.iOS.Analytics パッケージをインストールして、以下のような記述を追加すれば連携がおしまいです。

Gai.SharedInstance.GetTracker(/* TrackingName */, /* TrackingId */);
Gai.SharedInstance.TrackUncaughtExceptions = true;
Gai.SharedInstance.Logger.SetLogLevel(LogLevel.None);
Gai.SharedInstance.DispatchInterval = 5;

3.3. クラッシュレポートの取得

 Xamarin.iOS でのアプリ開発においても、アプリ開発者にはおなじみの Fabric/Crashlytics を利用することができますが、ここでは HockeyApp というサービスをご紹介します。HockeyApp を使うとクラッシュ時に C# のスタックトレースをサーバーサイドへ送出してくれます。導入ステップは以下のとおり。

  1. HockeyApp 上でアプリを登録して App Id を発行する
  2. HockeySDK.Xamarin を nuget でインストール
  3. AppDelegate に以下のコードを貼り付ける
  4. わざとどこかでクラッシュさせてクラッシュレポートが飛ぶかを確認する

 なお、iOS10系のシミュレータでは動作確認が上手くいかない不具合があるようで、実機のiOS10系を用いました。

        public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
        {
            // ...
            var manager = BITHockeyManager.SharedHockeyManager;
            manager.Configure("<!-- AppId をここにはる -->");
            manager.CrashManager.CrashManagerStatus = BITCrashManagerStatus.AutoSend;
            manager.StartManager();
            manager.Authenticator.AuthenticateInstallation();

            // ...
            return true;
        }

無事以下のようなクラッシュレポートを受け取ることができます

他にもベータ版配信の仕組みやアプリのアナリティクス機能も備えています。

4. まとめ

  • どの環境を使うか、きちんと選定しましょう
    • プロダクト開発の際は Xamarin.iOS を使うかを含めてしっかり検討しましょう
    • Xamarin.iOS(C#) にフィットする設計を検討しよう
    • クロスプラットフォームや環境の安定性において Xamarin.iOS には優位性があると考えています
  • iOS Native 経験があればほぼ躓くことなく開発可能
    • iOS Native 経験者はトライしてみよう
    • UIKit/Storyboard, Auto Layout の知識は活かせます

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください