Xamarin.iOS 基本プロジェクトからみるXcode(Objective-C/Swift)との比較
1 はじめに
前記事、「Xamarin.iOS テンプレート(Single View App)」で紹介した通り、Xamarin.iOSはプラットフォームライブラリを「薄くラッパー」したものになっています。 今回は、殆どの場合、最初の入り口となるであろうシンプルなプロジェクトで、VisualStudio(Xamarin/C#)とXcode(Objective-C及びSwift)の比較をしてみました。
2 プロジェクトの新規作成
(1)Objective-C
新規作成から「Single View Applicaton」を選択すると、ストーリーボードを使用した単一ビューのプロジェクトが作成されます。
プロジェクトのファイルツリーを見ると、主要な5種類のファイルが確認できます。
(2)Swift
プロジェクト作成は同じですが、「Language」で「Swift」を選択すると、Swiftによるプロジェクトになります。
ファイルは、Objective-Cとほぼ同じですが、Mainが無く主要ファイルは4種類になっています。
(3)Xamarin
新規作成から「Single View App(iPhone)」を選択すると、上記と同じくストーリーボードを使用した単一ビューのプロジェクトが作成されます。 ※一番上の「Blank App(iPhone)」はストーリーボードが使用されていません
ソリューションエクスプローラーで確認すると、主要なファイルは、Objective-C/Swiftで見たものと殆ど同じになっています。
各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」が使用されます。
(2)Xamarin
「Main Interface」で「MainStoryboard.storyboard」と指定されています。
6 Storyboard(④)
(1)Objective-C/Swift
ストーリーボードを使うと、アプリ画面のUIパーツのレイアウトや画面遷移を視覚的に作成することができます。(Xcode4.2以降の機能) ルートビューのクラス名は、ViewControllerと定義されています。
(2)Xamarin
Xamarinでもバージョン3以降、Storyboardによる画面設計ををVisualStudioから行う事ができるようになりました。 画面の描画に少しタイムラグがあり、逐次Xcodeと通信しながら動作しているいるようです。 ルートビューのクラス名は、RootViewControllerと定義されています。
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の本を参考にしています。