|
直到最近,要為蘋果的iPhone開發應用程序的唯一選擇就是一頭扎進蘋果的開發系統中。這意味著,你必須“愿意”在XCode IDE中編寫Objective-C代碼。對于很多開發人員,學習Objective-C被看作是一個巨大的障礙。特別對于哪些從來不用擔心內存管理、指針和C語言要負責處理的東西的開發人員來說,更是如此。
隨著MonoTouch框架(Novell的Mono Project的一部分)的出現,這一切都將改變。Mono Project是微軟.NET平臺的開源實現。其允許你在幾乎任何平臺上運行.NET應用程序,包括Apple、FreeBSD、Linux、Unix等等。MonoTouch是Mono Project的新組成部分,讓你能夠用C#和.NET平臺編寫可以運行在iPhone上的應用程序。
本篇文章的目的,就是提供MonoTouch平臺的一個完整介紹,讓大家知道到那里獲取必要的工具,MonoTouch有什么樣的限制,以及如何構建一個簡單的應用程序。
背景和限制
對于打算為iPhone開發應用的.NET開發人員而言,MonoTouch的出現無疑是一件好事。然而,在決定創建應用程序之前,有一些限制和背景知識需要先了解清楚。
它如何工作?
在創建MonoTouch應用程序的時候,大部分非UI方面的.NET 3.5功能依舊可用,或者一些還處于計劃之中(如.NET 4.0的功能)也囊括其中。這讓你可以使用很多業已熟悉的.NET Framework技術來編寫應用程序,包括Windows Communication Framework (WCF)、Workflow Foundation (WF)等等。也包括幾乎所有的基類庫(Base Class Library,BCL),涵蓋諸如垃圾收集(Garbage Collection)、線程、數學函數、System.NET、加密等。
對于可用的標準.NET程序集列表,見http://monotouch.NET/Documentation/Assemblies。MonoTouch是一種基礎.NET函數庫的特別定制版本,這也類似Silverlight和Moonlight的實現方式。
這意味著,你能夠使用MonoTouch的核心程序集來編譯標準的.NET 3.5代碼成相應的函數庫,并在你的應用程序中使用它們。因此,如果你有一個用于其它應用程序的特別函數庫,其包含著一些用于工程問題的高級數學函數,那么只需簡單地把這些代碼庫加入到你的MonoTouch解決方案中,并引用它。在你構建解決方案的時候,編譯器就利用MonoTouch核心函數庫對其進行編譯,接著就能在iPhone應用程序中使用它了。
MonoTouch也包括一些原生iPhone API的包裝函數庫,如訪問位置(Location,GPS)、加速計、地址簿等的函數。MonoTouch也提供相應的功能,讓你能夠調用那些尚未進行包裝的原生Objective-C函數庫,所以你可以直接和現存的Objective-C代碼進行互操作。
我如何創建用戶界面(UI),我能使用Silverlight嗎?
MonoTouch應用程序的UI需要使用蘋果的Interface Builder(界面創建器,IB)應用程序來創建,IB連同iPhone SDK一起提供。Interface Builder使用Cocoa Touch(蘋果用于iPhone的UI框架)控件對象,這些控件對象在iPhone上原生提供的。這意味著,你能在應用程序中使用所有的標準 iPhone控件,如選擇器(Pickers)、滑動條(Sliders)、按鈕等等。
你也能通過代碼來創建界面,即實例化Cocoa Touch對象后,把它們添加到應用程序的視圖(Views)中(關于視圖,后面會詳細講述)。
然而,你不能利用傳統的.NET技術,如Silverlight、WPF、WinForms等來創建MonoTouch界面。
Cocoa Touch使用一種融合了MVC(Model View Controller)模式思想的結構,我們將在后面一篇文章中介紹。
我如何分發我的應用?
MonoTouch應用程序的分發完全和傳統iPhone應用程序的分發一樣,既可以通過蘋果App Store,也可以通過企業部署。
App Store是一個在線資源庫,讓用戶可以付費購買(如果不是免費的話)和下載應用程序。可以從iTunes中訪問,或直接通過iPhone本身來訪問。為了得到通過App Store分發應用的許可,你必須向蘋果注冊,并支付每年99美元的年費。
企業部署方式就是為公司開發內部應用程序,并分發給員工等人員使用,無需把應用在App Store中列出。
什么是許可模型?
不像Mono那樣,MonoTouch不是開源的,且是一個收費產品。這意味著,如果你打算開發一些實際的應用,就必須購買軟件許可。
- 專業版($399)——單個的個人開發人員許可,讓你可以開發應用程序,并通過蘋果App Store來分發它們。
- 企業版($999)——單個的企業開發人員許可,讓你可以開發應用程序,并通過蘋果App Store來分發它們,或者進行企業部署。
- 企業版,5人($3999)——和企業版一樣,只是提供了5個坐席的授權。
以上所有選項都包括了一年的免費升級權益。
還有一個評估版本,你只能把應用部署到模擬器中。出于介紹的目的,我們只需要評估版本就行。
MonoTouch有哪些限制?
沒有即時(JIT)編譯
根據蘋果的iPhone政策,任何應用程序都不能包含需要JIT編譯的代碼。但是稍等,.NET確實能正確工作,是不?對,不過MonoTouch是通過把應用程序編譯為原生的iPhone程序集來跳過這個限制的。但是,這也帶來了幾個限制。
- 泛型——泛型是由JIT編譯器在運行時進行實例化的,然而,Mono具備一種提前(Ahead of Time ,AOT)編譯的模式,可以為類似List<T>這樣的泛型集合生成方法和屬性。而泛型的其他用法,例如泛型虛方法、泛型類型上的 P/Invokes和Dictionary<TKey, TValue>上的值類型,就不被支持(雖然存在Dictionary<TKey, TValue>的代替方法)。
- 動態代碼生成——因為動態代碼生成依賴于JIT編譯器,所以對任何動態語言編譯的過程也不能支持。包括System.Reflection.Emit、 Remoting和動態語言運行時(DLR)。
C#是唯一的語言
另外,目前用于編寫MonoTouch應用程序的唯一可用語言是C#。Visual Basic.NET有望在MonoTouch未來的發布中支持,不過此時此刻我們別無選擇。
更多信息
限制的完整列表和更多信息,可參見http://monotouch.NET/Documentation/Limitations。
入門
要進入為iPhone創建MonoTouch應用程序的大門,我們需要下面幾樣東西:
- 一個使用Intel CPU的Mac電腦,其要安裝MacOSX 10.5或10.6 (Leopard或Snow Leopard)
- 蘋果的iPhone SDK 3.0或更高版本
- Mono的當前版本
- MonoTouch SDK
- 一個IDE工具,如MonoDevelop或XCode,或一個文本編輯器程序
安裝著Leopard或Snow Leopard的Mac
這是最重要也是最容易忽視的需求。盡管,理論上你能在任何平臺上開發大部分應用程序,然而iPhone Simulator和Interface Builder只能在Leopard和Snow Leopard上運行。另外,編譯器本身用到了一些特定于Intel Mac機器的底層功能,所以購買這樣一臺電腦是絕對必須的。
蘋果的iPhone SDK
iPhone SDK可通過http://developer.apple.com/iphone/來免費下載,不過必須在蘋果網站上注冊,才能訪問這個地址。
在安裝了iPhone SDK后,要確保你能正常啟動iPhone Simulator。要啟動它,只需打開Spotlight,鍵入iPhone Simulator。
Mono
一旦你測試iPhone Simulator正常,那么就要安裝Mono for OSX的最新版。
Mono可以從http://mono-project.com/Downloads下載。記住要點擊“Intel”版本的鏈接,不要點CSDK版本。同樣,安裝MonoTouch SDK之前也需要安裝Mono的。Mono的安裝包是磁盤鏡像的形式,掛接鏡像,雙擊安裝包,根據安裝向導完成安裝過程。
MonoTouch SDK
接下來,下載和安裝最新的MonoTouch SDK。
你既可以在MonoTouch商店(http://monotouch.NET/Store)購買,購買后會收到一個下載鏈接,也可以從http://monotouch.NET/DownloadTrial下載評估版。如果購買了MonoTouch,你就能把應用程序部署到一臺正確配置了的iPhone上,不過也可像我這樣,僅僅在模擬器中運行。所以,目前而言試用/評估版就足夠了。
文本編輯器或集成開發環境(IDE)
如果你打算創建MonoTouch應用程序,所需的所有東西就是前面提及的,和一個文本編輯器。你能創建所有代碼文件,并用命令行(終端窗口)來手動編譯。這種方式雖然可行,但是實際操作起來可能會非常痛苦,所以我們還是需要使用一個IDE來開發我們的應用程序。
你可以編輯/hack一下XCode(隨iPhone SDK一起安裝)來利用MonoTouch的函數庫和編譯器,也可以使用MonoTouch版的MonoDevelop,其已經為MonoTouch應用程序做好所有配置了。我們理所當然要用MonoDevelop,所以訪問這里http://monodevelop.com/Download/Mac_MonoTouch來下載它。要安裝MonoDevelop,只用把下載文件拖到應用程序目錄中就行。
如果你已經正確安裝Mono,那么MonoDevelop應該可以正常啟動。
Hello World應用程序
現在,一切已經準備妥當,讓我們開始來嘗試開發點東西了。
MonoDevelop
首先,啟動MonoDevelop。你應該會看到和下圖類似的界面【譯者注:如果OSX的首選語言是中文的話,MonoDevelop的菜單和工具欄的文字顯示不正常,所以最好把English拖到語言選項的第一位】:
作為一個標準的IDE,看上去還是蠻熟悉的。它非常類似Visual Studio、SharpDevelop、Visual C# Express等等。
我們創建一個新解決方案,來包含iPhone項目。這里的解決方案和Visual Studio中的概念一樣,實際上你可以在MonoDevelop中打開Visual Studio創建的解決方案。在MonoDevelop中的一個不同點就是,你能夠在一個MonoDevelop實例中打開多個解決方案,正如下面的截圖所示:
這完全是由于在OSX中,你不能啟動MonoDevelop的多個實例(事實上,任何程序都不行),且沒有任何變通方法。所以,如果你需要在解決方案間切換(例如,你希望另外打開一個包含示例代碼的解決方案),你就能簡單地一次性打開多個。
那么,說了上面這么多,讓我們現在來創建一個解決方案吧。在菜單中,點File:New:Solution:
我們要創建一個如下面截圖所示的“iPhone MonoTouch Project”。選中,命名為Example_HelloWorld_1。
這里再次和Visual Studio中創建新解決方案的對話框很類似。點擊Forward ,顯示下一屏,直接點擊OK,因為我們不需要這些功能:
你現在應該可以看到如下所示的解決方案視圖了(注意,我展開了解決方案中的節點,以便顯示出所有文件和引用程序集):
我們來過一遍這些東西:
- References ——這個文件夾包含MonoTouch應用程序需要的基本引用。MonoTouch程序集包括特定于iPhone的任何東西,也包括了所有Cocoa Touch控件的包裝器,以及類似位置、數據等核心iPhone接口。以System.開頭的程序集是.NET的基類庫和運行時,其被裁減過以便能運行在 iPhone上。
- Main.cs ——這和控制臺應用程序、WPF應用程序等是一致的。在這里調用的是static void main() ,其是作為應用程序的入口點。過一下我們會仔細研究一下這個文件。
- MainWindow.xib和MainWindow.xib.designer.cs ——這個和Winforms Window或WPF Window類似。xib文件實際上要在Interface Builder中進行編輯,而designer.cs文件包含這個窗體的屬性。
讓我們來仔細研究一下Main.cs文件中的代碼:
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace Example_HelloWorld_1
{
public class Application
{
static void Main (string[] args)
{
UIApplication.Main (args);
}
}
// The name AppDelegate is referenced in the MainWindow.xib file.
public partial class AppDelegate : UIApplicationDelegate
{
// This method is invoked when the application has loaded its UI and its ready to run
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
// If you have defined a view, add it here:
//window.AddSubview(navigationController.View);
window.MakeKeyAndVisible ();
return true;
}
// This method is required in iPhoneOS 3.0
public override void OnActivated (UIApplication application)
{
}
}
}Outlets(對象關聯口)
我們來為之前添加的標簽和按鈕控件添加outlets,以便能在代碼中訪問它們。這點在Leopard和Snow Leopard上也有所區別,所以大家要嚴格遵循這里提到的正確指示。
【SNOW LEOPARD指示開始】
確保Library Window是打開的。點擊頂部的“Classes”標簽。點擊第一個下拉列表框,這個就是所謂的“Library”,滾動到最后選擇“Other Classes”。就會顯示在你的項目中存在的自定義類。從上面列表中選擇AppDelegate,接著選擇下面的“Outlets”標簽:
點擊“+”按鈕兩次來創建兩個新的Outlet。
【SNOW LEOPARD指示結束】
【LEOPARD指示開始】
首先,保證在Document Window中App Delegate是被選中的。如果App Delegate未被選中,那么在創建Outlets的時候,它們的屬性不會被創建,或者會在錯誤的地方創建。
接下來,來看Identity Inspector。Identity Inspector是Inspector窗口的最后一個標簽頁?,F在,在Identity Inspector中定位到“Class Outlets”部分。在Class Outlets上,點擊“+”按鈕兩次來創建兩個新的Outlet。
【LEOPARD指示結束】
每個outlet都具有一個名稱和一個類型。名稱代表了控件屬性的名字,這個類似于ASP.NET的ID,或WPF中的Name。類型是 Outlet的實際類型,比如UIButton、UILabel、UITextView等等。為了命名它們,在它們的名稱上雙擊,鍵入相應的名稱。對于我們之前添加的outlet來說,我們修改為“btnClickMe”和“lblResult”。
目前,它們兩者的類型都是“id”。如果你不改變類型,就能把它們掛接到任何東西上,因為id就意味著動態類型,本質上就是.NET世界中的“object”。id類型雖然好,不過我們打算把它們改為實際的類型。過一會我們會看到這樣做會有什么不同?,F在,雙擊btnClickMe的類型,鍵入“UIButton”。你的Class Outlets 窗口應該顯示如下這個樣子:
如果在里面沒有window的outlet,意味著你沒有在App Delegate創建outlet。如果這樣的話,刪除Outlets,保證在Document Window中選中App Delegate,重新創建outlets。
現在我們已經創建了這些outlets了,就需要實際地把它們關聯到我們的控件上。首先,在Inspector窗口上點擊第二個標簽頁,來選中 Connections Inspector。在Outlets部分,應該可以看到我們之前創建的兩個Outlets了。然而,你不能把它掛接到任何東西上。注意,“window”這個outlet已經掛接到“Window”對象上了。
為了掛接我們的Outlets,我們要從“Outlets”中的outlet圓點上,拖動到我們想要掛接的控件上。在這樣做的時候,我們將會看到如下所示的效果:
對兩個Outlet都進行這樣處理。你也可以從Connections Inspector拖到Document Window上。如果控件相互重疊的情況下,這樣就很有用。下面的截圖就描述了這種方式:
在我們這樣做的時候,你可能會注意到一些有趣的事情。因為設置lblResult的類型為UILabel,所以在我們把它的 Outlet拖到Window的時候,它只允許我們掛接到那些類型一致的控件上,在這個例子中就是UILabel。另外一方面,btnClickMe能被拖到任何東西上,因為它具有動態的ID類型。這就是我們要設置強類型outlet的一個原因,以便降低它掛接到錯誤控件上的可能性。當然,這不是必須的,不過這樣做是一個良好的習慣。
好的,現在我們創建好了界面了,outlets也掛接好了,讓我們回到MonoDevelop把一起串在一起。
回到MonoDevelop
如果你打開MainWindow.designer.cs,在其中會到兩個屬性:
[MonoTouch.Foundation.Connect("btnClickMe")]
private MonoTouch.UIKit.UIButton btnClickMe {
get {
return ((MonoTouch.UIKit.UIButton)(this.GetNativeField("btnClickMe")));
}
set {
this.SetNativeField("btnClickMe",value);
}
}
[MonoTouch.Foundation.Connect("lblResult")]
private MonoTouch.UIKit.UILabel lblResult {
get {
return ((MonoTouch.UIKit.UILabel)(this.GetNativeField("lblResult")));
}
set {
this.SetNativeField("lblResult",value);
}
}
NET技術:MonoTouch:用.NET開發iPhone應用,轉載需保留來源!
鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。