1. 程式人生 > >斯坦福大學 iOS 開發公開課總結

斯坦福大學 iOS 開發公開課總結

前言

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 的程式設計方式大為不同。

iOS 的 MVC 模式

MVC 模式算是客戶端類程式使用的設計模式的標配了。iOS 對於 Model, View 和 Controller 之間的相互呼叫有它自己的規範和約定,在公開課的 第一課 中,就介紹了應該如何將 MVC 模式應用在 iOS 開發中。主要的內容就體現在如下這張圖中 (圖片來自該公開課第一課的 配套 pdf 的第 37 頁):

我下面詳細介紹一下這幅圖的意思。

  • 首先圖中綠色的箭頭表示直接引用。直接引用直觀來說,就是說需要包含引用類的申明標頭檔案和類的例項變數。可以看到,只有 Controller 中,有對 Model 和 View 的直接引用。其中對 View 的直接引用體現為 IBOutlet。

  • 然後我們看 View 是怎麼向 Controller 通訊的。對於這個,iOS 中有 3 種常見的模式:

    1. 設定 View 對應的 Action Target。如設定 UIButton 的 Touch up inside 的 Action Target。
    2. 設定 View 的 delegate,如 UIAlertViewDelegate, UIActionSheetDelegate 等。
    3. 設定 View 的 data source, 如 UITableViewDataSource。
      通過這 3 種模式,View 達到了既能向 Controller 通訊,又不需要知道具體的 Controller 是誰是目的,這樣就和 Controller 解耦了。
  • 最後我們看 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 About synthesize

“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 執行緒) 進行。這個似乎不是約定,但是好多同學不知道,也寫在這兒吧。

UIView

剛開始對介面之間的跳轉很不理解,後來發現其實很簡單,就是一層一層疊起來的 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 File

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 上問問題。這對於英文不太好的同學這可能是一個障礙。不過反過來,習慣之後,通過這個鍛鍊了自己的英文水平,倒也是一大收穫。