【Xamarin】iOS 程式設計與 Xamarin.iOS

Tom Wang

 

 

一般而言,設計一個 iOS App 須使用 Mac 電腦搭配 Xcode 這套 IDE 完成。而大部分的教學文多強調先拖拉再一步步實作按鈕等功能,與實際開發人員的做法有出入。一台麥金塔電腦的售價加上每年 USD$99 的上架費用使人卻步。其實,開發一個 iOS App 一點都不難,而現在蘋果除了 iCloud Kit 以外也不再要求開發者需要開發者計畫才能進行實機測試。隨著 Xamarin 的推出,iOS App 也不再只能用 Objective-C 或 Swift 進行開發, 也能用 C#,接下來這篇文章會先從一個原生的 Xcode project 的檔案架構切入,並分析由 Objective-C,Swift 和 Xamarin 架構的 C# 在語法和使用上的不同之處。

 

原生iOS App 架構

一般從 App store 下載的 App 會被打包成 .ipa(相當於 Android 的 .apk),而開啓一個Xcode專案後會包含以下幾種檔案:

  • A. .h/.m/.Swift:程式的原始碼,所有的控制都是在這裡完成
  • B. .xib:Interface Builder 存放的 XML,包含使用者拖拉元件後的位置與屬性。 iOS App 依循 MVC(Model-View-Controller)架構,一個 xib 檔相當於 View,搭配 View Controller使用。與 Android 程式設計較不相同的是這個檔案不一定要存在,可在 UIView 中描述各個元件的屬性,而不須透過拖拉。
  • C. .storyboard:伴隨iOS 5推出,用法與Interface Builder相當,都能夠拖拉元件. 更進一步讓切換畫面不須以程式碼來完成。
  • D. .framework:即為上面 Core service 提供的框架,為二進制檔,與函式庫的概念相近。
  • E. .plist:用來存放用戶設定,以及一些與 App 本身有關的資訊,像是 CPU 架構等。

 

最基本的 iOS app --- 使用 Objective-C

Objective-C 是 C 語言的超集(Superset),也就是在一個 Objective-C 的檔案中可以完全使用 C 的語法而不會發生編譯錯誤。而在 iOS 程式設計中,會大量繼承 NSObject 這個 class。大部分的開發者會把class的宣告(declaration)與實作(inplementation)分成 .h 標頭檔與 .m 這兩個檔案。

 

#include <foundation/foundation.h> @interface foobar:NSObject {  @property (strong, atomic) bar; } -(void)foo:(int)arg @end
▲ 以上示範 Objective-C 2.0

 

在 Objective-C 中的 instance variable 在 2.0 之前須寫一對 setter/getter,非常麻煩。 透過 @property,編譯器會自動幫我們產生 get 和 set 這兩個 method(但開發者能夠覆寫(Override)這些方法)。大括號外宣告 method,若在括號前使用 + 號代表static。 而 property 也帶有參數,若不使用 ARC(Automatic Reference Counting), 會有 assign、retain、copy 三種,請參閱這篇 StackOverflow 的問答。若使用 ARC,則分為 Strong/Weak,atomic/nonatomic 兩種:

  • Strong:代表擁有該變數,不能使用代理(Delegate)。
  • Weak:由代理建構的物件,並不能直接控制。 若指向一個strong類型的物件被釋放時也會跟著被釋放。
  • Atomic:可防止一個 thread 完成前被另一個 thread 讀取。
  • Nonatomic:禁止 multithread 以提高性能。

另外還有 ReadWrite 和 Readonly,就和字面上一樣,若設為 Readonly 則只會生成 getter,使用者無法更改其值。

 

@implementation foobar @synthesize bar; -(void)foo:(int)arg{ Foobar *b = [[foobar alloc] init]; [b release]; } @end
▲ 以上則為 .m的架構

 

當前面使用 property 時,需搭配一個 synthesize 以產生 getter 和 setter。在此值得注意的是,setter 在 Objective-C 2.0 後可使用點(dot),但其他的method依然須使用中括號。而另外還有 Objective-C++,可加入 C++ 的類別,但有許多限制。

 

最基本的 iOS app --- 使用 Swift

學習 Objective-C 對初學者而言是一大挑戰,尤其是其複雜的記憶體管理。Swift 的架構與Python相似,不需一開始就宣告變數型態。 Objective-C 和 Swift 可同時出現在同一個專案之中。但 Swift 多了一些基本形態,如String等,有時須先轉成 Objective-C 有的型別。

 

import Cocoa class AppDelegate: NSObject,NSApplicationDelegate {  @IBOutlet weak var showbtn: NSButton!  @IBOutlet weak var thepop:NSPopover!  @IBAction func mybutton(sender: AnyObject) {   thepop.showRelativeToRect(sender.bounds, ofView: sender as! NSView , preferredEdge: NSRectEdge.MinX)  } }
▲ Swift 的程式碼較 Objective-C 簡潔

 

若開發者使用 Interface Builder 建構基本界面,程式碼中便會多出 IBOutlet 與 IBAction(可視為 Android 的 findviewbyid)。IBOutlet 可宣告介面上的元件,透過 IBAction,可以handle 介面上的元件所發出的事件。Swift 的特色是擁有 Optional type, 使得變數如果是 nil 的情況也能夠正常編譯, 程式碼中的驚嘆號代表強制解析,若執行到該行但物件不存在會出現 runtime error。而問號則多用於宣告變數, 宣告時物件可為 nil,通常搭配 if let 判斷式使用。

Xamarin.iOS

Xamarin 的特色是不必透過上述的 Objective-C 與 Swift 撰寫 iOS app,而是使用 C#。 雖然 Swift 編譯器已開源,Objective-C 也是 GCC 可編譯的語言之一,但 Cocoa touch 本身是專有軟體,所以在建置(Build)一個 Xamarin.iOS專案時,仍須準備一台裝好Xcode 的 Mac 電腦進行編譯。

在Mac上可以安裝 Xamarin studio來開發Xamarin.iOS,就算是PC上的 Visual Studio,也能夠藉由以 SSH(Secure Shell Hashing)連接 Mac 來開發。開出來的選項與一般 Xcode 無異,就連Interface Builder 的選項皆與 Xcode 相同

Xamarin.iOS 擁有的類別與 Xcode 同步,但也有自己的 reference。所有的 Objective-C 與 Swift 檔案都改成 .cs, 至於流程控制、事件傳遞等都與原生的相同,但須符合C#的語法,而前面要 using 的模組也與 Windows form 相似。

001

 

撰寫 Xamarin.iOS 程式時,一樣能夠參考蘋果官方的 iOS API Reference,但有幾個地方需要注意

  • • 方法的大小寫
    • Objective-C / Swift:viewDidLoad
    • Xamarin:ViewDidLoad
  • • 匯入模組
    • o Swift:import
    • o Objective-C:include 或 import
    • o Xamarin:Using
  • • Xamarin 須宣告 namespace
  • • Xamarin 的建構子(Constructor)須符合 C# 的語法,如下
    • o Xamarin

var height = new UITextField {  Frame = new CGRect(50, 105, 200, 30),  BorderStyle = UITextBorderStyle.RoundedRect,  Placeholder = "Height" };

    • o Swift

var height = UITextField(Frame:CGRectMake(50, 105, 200, 30), borderStyle: .RoundRect, placeHolder: "Height")

    • o Objective-C

UITextField *height = [[UITextField alloc] initWithFrame: CGRectMake(50, 105, 200, 30)];

  • • Xamarin 可使用 PCL(Portable Class Library),將某些函數模組化後移植到其他平台,如 Xamarin.Android

結語

每一種程式語言都有它的獨特性。 其中 Objective-C 可透過 Bridging Header 與 Swift 混用,故一些網路上的教學文章提供的寫法仍值得參考,且一些第三方 API 也能透過這種方式使用。 Xamarin.iOS 提供用 C# 撰寫 iOS 應用程式的方式,語法類似 Java,對於寫過 Android app 的開發人員來說非常容易上手,同時也提供了 Objective-C 的綁定(Binding)。 物件導向程式語言的架構大同小異,大多是語法和用法上的差異,而學 App 要注意的通常是流程控制與不同 UI 元件和服務(Service)的使用方式。 Xamarin 讓我們可以用 C# 搞定所有平台的 App,同時能夠學到原生 App 的架構和各種功能的實作方法,很值得 App 初學者學習。

參考資料

https://www.zhihu.com/question/20350816 https://shenfive.pixnet.net/blog/post/48054812-%EF%BC%A0property- https://kaochenlong.com/2010/12/08/property-and-synthesize/ https://www.raywenderlich.com/113388/storyboards-tutorial-in-ios-9-part-1 https://developer.apple.com/reference/uikit/uitextfield