iPhone 開發相關的教程中最有名的,當數斯坦福大學發布的 “iPhone 開發公開課 “ 了。此公開課在以前叫做《iPhone 開發教程》,今年由於平板電腦的流行,所以也加入了 ipad 開發相關的課程。在 網易公開課 上,有 該教程 的 2010 年錄象,並且前面 15 集帶中文字幕文件,非常適合初學者學習。
在這裡順便說一下,網易公開課上的 28 集其實並不需要全部看完。真正的課程只有前面 12 集。後面的課程都是請一些業界的名人講他們成功的 app 以及學生的作品展示,可看可不看。所以大家不要被 28 集這麼多嚇到。
由於近一年來 iOS5 以及 xcode4 的發布,蘋果對原有的開發環境 xcode 以及開發語言 Objective-C 都有改進,所以原有的教程中很多內容不再適用了。例如新的 xcode4 將 Interface Builder 集成到 xcode 中,整個 IDE 布局和快捷鍵完全大變樣,又比如蘋果為 Objective-c 引用了 ARC 和 Storyboard,這些都使得 app 的編程方式大為不同。
值得高興的是,斯坦福大學最近更新了該公開課的 2011 年秋季錄象,免費下載地址是:http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=480479762,不過現在該公開課還沒有翻譯,只能看英文原版了。新的課程相比以前要短了許多,一共只有 9 課。我大概快速看了一遍,總結一些心得給大家。
MVC 模式算是客戶端類程序使用的設計模式的標配了。iOS 對於 Model, View 和 Controller 之間的相互調用有它自己的規范和約定,在公開課的 第一課 中,就介紹了應該如何將 MVC 模式應用在 iOS 開發中。主要的內容就體現在如下這張圖中 (圖片來自該公開課第一課的 配套 pdf 的第 37 頁):
我下面詳細介紹一下這幅圖的意思。
首先圖中綠色的箭頭表示直接引用。直接引用直觀來說,就是說需要包含引用類的申明頭文件和類的實例變量。可以看到,只有 Controller 中,有對 Model 和 View 的直接引用。其中對 View 的直接引用體現為 IBOutlet。
然後我們看 View 是怎麼向 Controller 通訊的。對於這個,iOS 中有 3 種常見的模式:
設置 View 對應的 Action Target。如設置 UIButton 的 Touch up inside 的 Action Target。設置 View 的 delegate,如 UIAlertViewDelegate, UIActionSheetDelegate 等。設置 View 的 data source, 如 UITableViewDataSource。最後我們看 Model。Model 在圖上有一個信號塔類似的圖形,旁邊寫著 Notification & KVO。這表明 Model 主要是通過 Notification 和 KVO 來和 Controller 通訊的。關於 Notification,我寫了一個模版代碼片段如下:(關於代碼片段的管理,推薦大家看我寫的另一篇文章:使用 Github 來管理 xcode4 中的代碼片段
// 監聽通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(<#methodName#>) name:kLoginNotification object:nil]; // 取消監聽 [[NSNotificationCenter defaultCenter] removeObserver:self]; // 發送通知 NSDictionary * userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:200] forKey:@"code"]; [[NSNotificationCenter defaultCenter] postNotificationName:<#notification_name#> object:self userInfo:userInfo];
所以,對於初學者,要正確地使用 MVC 模式還是挺難的,回想我們以前做公司某產品 iPhone 版的時候,就有一些 Model 層直接依賴了 Controller 層,比如 Model 層更新數據失敗了,直接調用 Controller 層顯示出一個失敗的提示界面。這樣層次劃分不清,造成我們做 ipad 版的時候很痛苦。最後我們做了代碼重構,把 Model 的相應改變都用 Notification 來完成,使得在做 ipad 版開發時輕松了很多。
“Convention over configuration”(約定高於配置)成就了 Ruby On Rails,而 iOS 也有很多編程的約定。這些約定單獨看沒有什麼好處,約定的最大好處就是,如果大家都遵守它,那麼代碼風格會趨於一致,你會很方便地讀懂或修改別人的代碼。
我們可以從第一課 PPT 的第 50 頁看到如下的代碼:
從圖中可以看到,該課程推薦大家在使用 synthesize 關鍵字時,為 property 設置一個下劃線前綴。我也看過一些 iPhone 的開源項目,比如 facebook 開源的 three20 ,它是遵守了這樣的約定的。
其它的約定還包括:
以 new, copy, alloc 開頭的方法,都應當由調用者來 release,而其它方法,都返回一個 autorelease 對象。通常 iPhone 頂部的 bar 應該用 UINavigation 控件,而底部的 bar 應該用 UIToolbar 控件。所有的 UI 操作都應該在主線程 (UI 線程) 進行。這個似乎不是約定,但是好多同學不知道,也寫在這兒吧。剛開始對界面之間的跳轉很不理解,後來發現其實很簡單,就是一層一層疊起來的 View。從 View A 上點擊一個按鈕跳轉到 View B,其實就是把 View B“蓋” 在 View A 上面而已。
而 “蓋” 的方式有好多種,通常的方法有 2 種:
一 . 用 UINavigationController 把 View B push 進來。
[self.navigationController pushViewController:nextView animated:YES];
二 . 用 presentModalViewController 方法把 View B 蓋在上面。
[self presentModalViewController:nextView animated:YES];
除此之外,其實還有一種山寨方法,即把 View A 和 View B 都用 addSubView 加到 AppDelegate 類的 self.window 上。然後就可以調用 bringSubviewToFront 把 View B 顯示出來了,如下所示:
// AppDelegate.m 類 [self.window addSubview:viewB]; [self.window addSubview:viewA]; // 在需要時調用 [self.window bringSubviewToFront:viewB];
上面說的是界面之間的跳轉。對於一個界面內,其控件的布局其實也是一個一個疊起來的,之所以說疊,是指如果 2 個控件如果有重疊部分,那麼處於上面的那個控件會蓋住下面的。
Nib 文件實際上內部格式是 XML,而它本身並不編譯成任何二進制代碼。所以你如果用 iFile 之類的軟件在 iPhone 上查看一些安裝好的軟件的目錄,可以看到很多的以 nib 結尾的文件,這些就是該軟件的界面文件。雖然這些 XML 經過了一些壓縮轉換,但是我們還是可以看到一些信息,例如它使用了哪些系統控件等。
Nib 文件剛開始給我的感覺很神秘,後來發現它其實就是用於可視化的編輯 View 類用的。其中的 File’s Owner 一欄,用於表示這個 View 對應的 Controller 類。通常情況下,Controller 類會有一個名為 view 的變量,指向這個 view 的實例,我們也可以建立多個 IBOutlet 變量,指向這個 view 上的控件,以便做一些界面上的控制。
在 Interface Builder 上還有一個好處,是可以方便的將 View 的事件與 Controller 的 IBAction 綁定。只需要按住 Ctrl 鍵,從控件往 File’s Owner 一欄拖拽,即可看到可以綁定的方法列表。其實這些只是簡化了我們的工作,如果完全拋開 Interface Builder,我們一樣可以完成這些工作。我所知道業界的一些 iOS 開發部門,為了多人協作更加方便,更是強制不允許使用 Interface Builder,一切界面工作都在代碼中完成。如果你用文本編輯器打開 Nib 文件看過,就能理解這樣做是有道理的。因為如果 2 個同時編輯一個界面文件,那麼沖突的可能性是 100%,而且,從 svn 結出的沖突信息上看,你根本無法修正它。下面的代碼演示了如何不用 Interface Builder 來添加控件以及綁定 UI 事件。
// SampleViewController.m 的 viewDidLoad 方法片段 // 添加 Table View 控件 UITableView * tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, 320, 400)]; [self.view addSubview:tableView]; tableView.delegate = self; [tableView release]; // 添加 Button 控件 self.button = [[[UIButton alloc] initWithFrame:CGRectMake(0, 0, 200, 100)] autorelease]; [self.view addSubview:self.button]; // 綁定事件 [self.button addTarget:self action:@selector(buttonPressed) forControlEvents:(UIControlEventTouchUpInside)];
總體來講,學習 iOS 開發還是比較容易的。我大概花了一個月時間學習 iPhone 開發,就可以邊做邊學了。
蘋果的設計對於開發者來說是非常友好的,很多時候使用相應的控件就行了,都不用操心底層細節。不象 Android 開發,一會兒要考慮不同手機分辨率不一樣了,一會兒又要考慮有些不是觸摸屏了,一會兒又發現某款手機的 cpu 內存太弱了跑不起來,需要優化程序。另外,Objective-C 相對於 C++ 語言來說,要簡單優雅得多,而且更加強大,所以做 iOS 的開發者很省心。
要說到不爽的地方,就是 iOS 開發相關的中文資料實在是太少了。要學習它,基本上需要查看蘋果的官方英文文檔以及 WWDC 大會視頻,還有去 stackoverflow 上問問題。這對於英文不太好的同學這可能是一個障礙。不過反過來,習慣之後,通過這個鍛煉了自己的英文水平,倒也是一大收獲。