Xamarin.iOS 基本プロジェクトからみるXcode(Objective-C/Swift)との比較

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

1 はじめに

前記事、「Xamarin.iOS テンプレート(Single View App)」で紹介した通り、Xamarin.iOSはプラットフォームライブラリを「薄くラッパー」したものになっています。 今回は、殆どの場合、最初の入り口となるであろうシンプルなプロジェクトで、VisualStudio(Xamarin/C#)とXcode(Objective-C及びSwift)の比較をしてみました。

2 プロジェクトの新規作成

(1)Objective-C

新規作成から「Single View Applicaton」を選択すると、ストーリーボードを使用した単一ビューのプロジェクトが作成されます。

CompiOS001

プロジェクトのファイルツリーを見ると、主要な5種類のファイルが確認できます。

CompiOS002

(2)Swift

プロジェクト作成は同じですが、「Language」で「Swift」を選択すると、Swiftによるプロジェクトになります。 CompiOS003

ファイルは、Objective-Cとほぼ同じですが、Mainが無く主要ファイルは4種類になっています。 CompiOS004

(3)Xamarin

新規作成から「Single View App(iPhone)」を選択すると、上記と同じくストーリーボードを使用した単一ビューのプロジェクトが作成されます。 ※一番上の「Blank App(iPhone)」はストーリーボードが使用されていません

CompiOS005

ソリューションエクスプローラーで確認すると、主要なファイルは、Objective-C/Swiftで見たものと殆ど同じになっています。

CompiOS006

各IDEのファイルツリーにおいて、赤字で①〜⑤のナンバーリングをしましたが、以降、この5種類のファイルを比較してみることにします。

3 Main(①)

(1)Objective-C

main.mでは、UIApplicationMainでアプリケーションの初期化が行われています。 UIApplicationMainの第4パラメータにはアプリケーションデリゲートのクラスが指定されますが、ここでは「AppDelegate」を指定してるのが確認できます。

Main.m

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

(2)Swift

Swiftでは、前述のとおりMainとなるファイルはありません。AppDelegate.swiftの「@UIApplicationMain」が同等の意味になります。

AppDelegate.swift

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

(3)Xamarin

Main.csでは、UIApplicationクラスのMainメソッドでUIKit関連の初期化が行われています。 Mainメソッドの第3パラメータで、デリゲートクラスの名前「AppDelegate」が設定されています。

Main.cs

using UIKit;
namespace App1 {
    public class Application {
        private static void Main(string[] args) {
            UIApplication.Main(args, null, "AppDelegate");
        }
    }
}

4 AppDelegate(②)

アプリケーションデリゲートは、アプリケーションの起動や終了や中断などの処理を行います。

(1)Objective-C

AppDelegate.m

#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate

//アプリの起動時
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    return YES;
}

//アプリが非Activeになる直前
- (void)applicationWillResignActive:(UIApplication *)application {
}

//アプリが非Activeになりバックグランド実行になった時
- (void)applicationDidEnterBackground:(UIApplication *)application {
}

//2回目以降の起動時(Backgroundにアプリがある場合)
- (void)applicationWillEnterForeground:(UIApplication *)application {
}

//アプリがActiveになった時
- (void)applicationDidBecomeActive:(UIApplication *)application {
}

//システムからのアプリ終了時
- (void)applicationWillTerminate:(UIApplication *)application {
}
@end

AppDelegateの各メソッドは、コメントに記載したタイミングで呼び出されます。

(2)Swift

Swiftのメソッド名は、Objective-Cと同じです。

AppDelegate.swift

import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        return true
    }

    func applicationWillResignActive(application: UIApplication) {   }

    func applicationDidEnterBackground(application: UIApplication) {   }

    func applicationWillEnterForeground(application: UIApplication) {   }

    func applicationDidBecomeActive(application: UIApplication) {    }

    func applicationWillTerminate(application: UIApplication) {    }
}

(3)Xamarin

AppDelegate.cs

using Foundation;
using UIKit;

[Register("AppDelegate")]
public partial class AppDelegate : UIApplicationDelegate {
    public override UIWindow Window { get; set; }
    public override void OnResignActivation(UIApplication application) { }
    public override void DidEnterBackground(UIApplication application) { }
    public override void WillEnterForeground(UIApplication application) { }
    public override void WillTerminate(UIApplication application) { }
}

Xamarinでは、殆ど同じ名前のメソッドが適宜されており、それをオーバーライドすることで、処理を記述します。

5 Info.plist(③)

AppDelegateの初期化が終了したのちに、最初に表示されるルートビューをストーリーボードで作成した場合、その名前はInfo.plistで指定されます。

(1)Objective-C/Swift

「Main storyboard file base name」で「Main」と指定されており、「Main.storyboard」が使用されます。 CompiOS007

(2)Xamarin

「Main Interface」で「MainStoryboard.storyboard」と指定されています。 CompiOS008

6 Storyboard(④)

(1)Objective-C/Swift

ストーリーボードを使うと、アプリ画面のUIパーツのレイアウトや画面遷移を視覚的に作成することができます。(Xcode4.2以降の機能) ルートビューのクラス名は、ViewControllerと定義されています。 CompiOS009

(2)Xamarin

Xamarinでもバージョン3以降、Storyboardによる画面設計ををVisualStudioから行う事ができるようになりました。 画面の描画に少しタイムラグがあり、逐次Xcodeと通信しながら動作しているいるようです。 ルートビューのクラス名は、RootViewControllerと定義されています。

CompiOS010

7 ViewController(⑤)

ビューの表示と管理を担当するオブジェクトです。

(1)Objective-C

ViewController.m

#import "ViewController.h"
@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
@end

UIViewControllerのメソッドには、次のようなものがあります。

-(void)viewDidLoad //初回ロードされた時のみ -(void)viewWillAppear:(BOOL)animated //画面が表示される都度 -(void)viewDidAppear:(BOOL)animated //画面が表示された後 -(void)viewWillDisappear:(BOOL)animated //画面が閉じる前 -(void)viewDidDisappear:(BOOL)animated //画面が閉じた後 -(void)viewDidUnload //画面がアンロードされたとき -(void)didReceiveMemoryWarning //メモリ不足時

(2)Swift

Swiftのメソッド名は、Objective-Cと同じです。

ViewController.swift

import UIKit
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

(3)Xamarin

RootViewController.cs

public partial class RootViewController : UIViewController {
        public RootViewController(IntPtr handle) : base(handle) { }

        public override void DidReceiveMemoryWarning() {
            base.DidReceiveMemoryWarning();
        }


        public override void ViewDidLoad() {
            base.ViewDidLoad();
        }

        public override void ViewWillAppear(bool animated) {
            base.ViewWillAppear(animated);
        }

        public override void ViewDidAppear(bool animated) {
            base.ViewDidAppear(animated);
        }

        public override void ViewWillDisappear(bool animated) {
            base.ViewWillDisappear(animated);
        }

        public override void ViewDidDisappear(bool animated) {
            base.ViewDidDisappear(animated);
        }
}

UIViewControllerの継承したRootViewControllerとなっていますが、こちらも、iOSの場合とほぼ同じ名前(アッパーキャメルケースになっている)のメソッドが定義されています。

8 まとめ

今回は、シンプルなプロジェクトを作成した際に生成される5種類のファイルについて、3種類のIDEで比較してみました。 ある程度の法則を見つければ、どの言語のドキュメントを見ても、簡単に変換可能だと思います。 私の場合も、Xamarin.iOSを書く際に、SwiftやObjective-Cの本を参考にしています。

9 参考リンク


「iOS SDKで始めるObjective-C入門」
Xcodeの概要


この辺でXamarin導入による 効果と限界をしっかり把握してみよう MVP Community Camp 2015
Xamarin記事一覧(SAPPOROWORKSの覚書)