重要:這是針對于正在開發中的API或技術的預備文檔(預發布版本)。蘋果提供這份文檔的目的是幫助你按照文中描述的方式對技術的選擇及界面的設計開發進行規劃。這些信息有可能發生變化,因此根據本文檔的軟件開發應當基于最終版本的操作系統和文檔進行測試。該文檔的新版本或許會隨著API或相關技術未來的發展而進行更新。
翻譯自蘋果官網:
本教程讓你熟悉 Xcode 開發工具。對項目結構有個初步了解,并學習如何使用 Xcode 的一些基本組件來為我們的 app 構建一個簡單的界面然后在模擬器中查看它。最后,app 應該像這樣:
[圖片上傳失敗...(image-bcde35-1608214722107)]
學習目標:
學完本教程,你將學會:
- 在 Xcode 中創建新項目
- 認識 Xcode 項目模板創建的一些重要文件的功能
- 在項目中打開和切換文件
- 在模擬器中運行 app
- 在 storyboard 中添加、移動界面控件并調整它們的尺寸
- 使用自動布局構建一個自適應用戶屏幕尺寸的界面
創建新項目
Xcode 隨附了幾個內建應用程序模板,可用于開發常見的 iOS 應用程序,如游戲、基于標簽瀏覽的應用程序和基于表格視圖的應用程序。這些模板大都預先配置了界面和源代碼文件,可作為您進行開發工作的起點。本教程會從最基礎的模板開始:Single View Application。
步驟
-
從 /Applications 目錄打開 Xcode。
Xcode 歡迎窗口會出現。如果出現的是項目窗口,而不是歡迎窗口,請不要著急;這說明您可能曾在 Xcode 中創建或打開過項目。您只需在接下來的步驟中,使用菜單項來創建項目。
[圖片上傳失敗...(image-863682-1608214722107)]
在歡迎窗口中,點按 Create a new Xcode project(或選取 File > New > Project)。
Xcode 將打開一個新窗口并顯示對話框,讓您從中選取一個模板。在對話框左邊的 iOS 部分,選擇 Application 。
-
在對話框的主區域中,點按 Single View Application,然后點按 Next。
[圖片上傳失敗...(image-6ae01d-1608214722107)]
-
在出現的對話框中,給應用程序命名并選取應用程序的其他選項。
- Product Name:FoodTracker
Xcode 會使用您輸入的產品名稱給您的項目和應用程序命名。 - Organization Name: 公司或你自己的名字??梢灾每?。
- Organization Identifier: 公司標識符(如果有)。如果沒有,請使用 com.example。
- Bundle Identifier: 根據 product name 和 organization identifier 自動生成。
- Language: Swift
- Devices: Universal
Universal app 可以同時運行在 iPhone 和 iPad 兩種設備上。 - Use Core Date: 不選中。
- Include Unit Tests: 選中。
- Include UI Tests: 不選中。
[圖片上傳失敗...(image-b9f1da-1608214722107)]
- Product Name:FoodTracker
點擊 Next。
在出現的對話框中,選取項目的存放位置,然后點按 Create。
Xcode 會在工作區窗口中打開新項目,窗口的外觀如下:
[圖片上傳失敗...(image-dbf5e6-1608214722107)]
在工作區窗口,你可能看到一個三角形警告消息,說“沒有代碼簽名標志”。提醒你沒有為 iOS 開發設置 Xcode 證書,但不要擔心,本教程并不需要證書。
熟悉 Xcode
Xcode 包括了您創建應用程序時所需的一切。它不僅整理了創建應用程序時所需的文件,還提供了代碼和界面編輯器,可讓您構建和運行應用程序,并擁有強大的集成調試程序。
請花幾分鐘時間來熟悉 Xcode 工作區窗口。在接下來的整個教程中,您將會用到下面窗口中標出的區域。不要被所有這些嚇倒,當某個區域需要用到時再去詳述更多相關信息。
[圖片上傳失敗...(image-322788-1608214722107)]
運行模擬器
由于項目是基于 Xcode 模板創建的,因此基本的應用程序環境已經自動為您設置好了。即使沒有編寫任何代碼,也可以構建和運行 Single View Application 模板,而無需進行任何額外的配置。
構建和運行您的 app,可以使用 Xcode 自帶的 iOS 模擬器。顧名思義,iOS 模擬器可模擬在 iOS 設備上運行 app,讓您初步了解它的外觀和行為。
它可模擬多種不同類型的硬件,包括屏幕大小不同的 iPad、iPhone 等等。因此,您可以模擬在任何一款開發目標設備上運行 app。在本教程中,我們選擇使用“iPhone 6”。
在 iOS 模擬器中運行 app
-
從 Xcode 工具欄的 Scheme 彈出菜單中選取 iPhone 6。
在 Scheme 彈出菜單中可以選擇你喜歡的 Simulator 或 Device 來運行你的 app,但請確保選擇了 iPhone 6 Simulator,而不是 iOS Device。
[圖片上傳失敗...(image-51f003-1608214722107)]
-
點按 Xcode 工具欄左上角的 Run 按鈕。
[圖片上傳失敗...(image-6894bb-1608214722107)]
或者可以選取 Product > Run(或按下 Command-R)。
如果是首次運行 app,Xcode 會詢問您是否要在 Mac 上啟用開發者模式。開發者模式可讓 Xcode 訪問特定的調試功能,無需每次都輸入密碼。請決定是否要啟用開發者模式,然后按照提示操作。
[圖片上傳失敗...(image-fbbdc4-1608214722107)]
如果選擇不啟用,可能稍后會要求您輸入密碼。本課程假定已啟用了開發者模式。
-
構建過程完成后,請看 Xcode 工具欄。
Xcode 會在工具欄中間的活動顯示窗口中顯示有關構建過程的消息。
Xcode 完成項目生成后,模擬器會自動啟動。首次啟動時可能需要幾分鐘時間。
模擬器以你指定的 iPhone 模式開啟。在模擬的 iPhone 屏幕上,模擬器啟動了你的 app。在 app 完成啟動前,你會短暫看到一個帶有 app 名字 FoodTracker 的啟動界面。
[圖片上傳失敗...(image-89ca76-1608214722108)]
之后會看到這樣的界面
[圖片上傳失敗...(image-6c1ae0-1608214722108)]
一如其名,Single View Application 模板并未包括過多的代碼,僅會顯示一個白色的屏幕。其他模板會有更多復雜的行為,因此在擴展模板制作自己的 app 之前,先要弄清楚模板的用處,這一點很重要。而要做到這一點,一個很好的方式,就是先不做任何修改,直接運行模板。
請選取 Simulator > Quit Simulator(或按下 Command-Q)來退出模擬器。
檢查源代碼
Single View Application 模板附帶了少量現成的源代碼來設置 app 環境,首先,讓我們看下 AppDelegate.swift 文件。
查看 AppDelegate.swift 源文件
-
確保在導航區域打開了項目導航。
項目導航會顯示項目中的所有文件。如果項目導航未打開,請點按導航選擇欄最左邊的按鈕。(或者選擇 View -> Navigators -> Show Project Navigator。)[圖片上傳失敗...(image-ca7c47-1608214722108)]
如果需要,點擊項目導航旁邊的提示三角打開 FoodTracker 文件夾。
-
選擇 AppDelegate.swift。
Xcode 會在主編輯器窗口區域打開源文件。[圖片上傳失敗...(image-e1c5cd-1608214722108)]
或者,雙擊 AppDelegate.swift 文件在單獨的窗口中打開它。
App Delegate 源文件
AppDelegate.swift 源文件有兩個主要功能:
- 為你的 app 創建入口以及一個 run loop 來傳遞事件。這項工作由文件的頂部 UIApplicationMain 屬性完成(@UIApplicationMain)。UIApplicationMain 創建一個 application 對象負責管理 app 和 app delegate 對象的生命周期。
- 定義 AppDelegate 類,它創建 window 供你的 app 的內容進行渲染,并響應 app 狀態轉換。 AppDelegate 類主要用于寫自定義系統級代碼的。
AppDelegate 類包含一個屬性:window。它使用這個屬性來保持窗口跟蹤并在窗口中繪制 app 的內容。window 屬性是可選的,意味著有時候它是空的。
var window: UIWindow?
AppDelegate 類也包含一些重要模板方法的實現。這些預定義的方法允許 application 對象與 app delegate 交流。
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
func applicationWillResignActive(application: UIApplication)
func applicationDidEnterBackground(application: UIApplication)
func applicationWillEnterForeground(application: UIApplication)
func applicationDidBecomeActive(application: UIApplication)
func applicationWillTerminate(application: UIApplication)
在 app 狀態變化過程中 - 例如,app 啟動狀態,過渡到后臺狀態,和 app 終止狀態 - application 對象會調用 app delegate 中相應的方法,給它一個機會來做合適的響應。你不需要做任何特別的事情來確保這些方法在正確時間被調用 - application 對象為你做了這部分工作了。
這些自動實現的方法中的每一個都有默認的功能。如果讓模板實現為空或者從 AppDelegate 類中刪除它,當方法被調用時你會得到默認的功能。添加自定義代碼到這些模板方法,當方法被調用了代碼相應會執行。在本課中,你不會使用任何自定義 app delegate 代碼,所以你不需要對 AppDelegate.swift 文件做任何修改。
View Controller 源文件
Single View Application 模板生成了另外一個源文件: ViewController.swift 文件。在項目導航中選擇 ViewController.swift 查看。
[圖片上傳失敗...(image-87e108-1608214722108)]
文件定義了 UIViewController 的子類 ViewController。此刻,這個類簡單繼承 UIViewController 定義的所有功能。為了覆寫或擴展這些功能,覆寫 UIViewController 定義的方法(就像你看到的 ViewController.swift 文件中的 viewDidLoad() 和 didReceiveMemoryWarning() 方法),或者實現自定義的方法。
盡管模板為你生成了 didReceiveMemoryWarning() 方法,在本教程并不會用到,所以刪掉它吧。
現在,ViewController.swift 代碼應該像這樣:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
稍后會在這個文件中寫代碼。
打開 Storyboard
準備好使用 storyboard 工作吧。它是 app 用戶界面的可視化描述,顯示界面的內容和界面間的跳轉。當設計界面的時候可以實時看到效果 - 所見即所得。
打開 storyboard
- 在項目導航中,選擇 Main.storyboard。
Xcode 會在編輯區的可視化界面編輯器 Interface Builder 中打開 storyboard。storyboard 的背景就是畫板(canvas)。使用畫板來添加和排列 UI 控件。
storyboard 應該類似這樣:
[圖片上傳失敗...(image-d8a038-1608214722108)]
至此,app 的 storyboard 中包含了一個場景(scene),代表 app 滿屏的內容。在場景的左邊有個箭頭表示這個場景是 storyboard 的入口,意味著當 app 啟動的時候這個場景最先加載。現在,你看到場景僅僅包含單一控制器管理的視圖。不久你會學到更多關于視圖和視圖控制器的用處。
在 iPhone 6 模擬器中運行你的 app,會在設備屏幕上看到場景中的視圖。但是在畫板中查看場景時,你會注意到它的尺寸并不是 iPhone 6 屏幕那么大。因為畫板中的場景是界面的廣義描繪,它可以被用于表示任何方向的任何設備。使用它創建一個自適應界面,該界面會自動調節大小,以便能適配當前設備和方向。
構建基本 UI
是時候構建基本界面了。開始為場景做一個 UI 讓你添加一份新的食物到你的食物跟蹤 app,FoodTracker。
Xcode 提供了可以添加到 storyboard 中的對象庫。有些如 button 和 text fields 等能顯示在界面中。其他的,如視圖控制器和手勢,主要用于定義 app 的功能而不是顯示在屏幕上。
在 UI 中顯示的控件被稱為視圖,視圖向用戶展示內容。它們是構建你的 UI 的基本模塊,它們用一種清晰優雅的方式展示你的內容,視圖有一些很有用內置行為,包括在屏幕上顯示和響應用戶的輸入。
iOS 中所有視圖對象都是 UIView 或它的一個子類。許多 UIView 的子類有高度定制的外觀和功能。通過往你的場景中添加 UITextField,一個UIView 的子類。它讓用戶輸入單行文本來作為食物的名字。
往場景中添加文本框
-
打開對象庫。
對象庫在 Xcode 右邊的實用工具區的底部。如果沒有看到它,點擊庫選擇欄左邊的第三個按鈕(或者選擇 View > Utilities > Show Object Library)[圖片上傳失敗...(image-651abe-1608214722108)]
出現一個列表顯示每個對象的名字、描述和外觀。
在對象庫的搜索框中輸入 text field 快速找到 Text Field對象。
-
從對象庫中拖動 Text Field 對象到場景中。
[圖片上傳失敗...(image-28bf08-1608214722108)]
如果需要,選擇 Editor > Canvas > Zoom 來縮小畫板尺寸。
-
拖動文本框使它位于場景的前半部分,并與場景的左邊緣對齊。
當達到下圖效果停止拖動。[圖片上傳失敗...(image-ce4e5-1608214722108)]
藍色的布局引導線幫助你放置文本框。當你拖動文本框接近另一個對象或調整它的尺寸時布局引導線可見;而放開文本框線就消失了;
-
如果需要,點擊文本框激活 resize handles。
resize handles 是在控件邊緣出現的小白色方塊,通過拖動它來調整 UI 控件的尺寸。選中對象激活控件的 resize handles。如果文本框像下面這樣,說明已經為調整大小做好準備了;如果沒有,請在畫板中選中它。[圖片上傳失敗...(image-1f45a7-1608214722108)]
-
調整文本框左右邊距直到看到三個垂直布局引導線;左邊緣對齊、水平居中對齊和右邊緣對齊。
[圖片上傳失敗...(image-ddbc29-1608214722108)]
盡管在場景中有文本框,但并沒有指引用戶在文本框中輸入什么。使用文本框的 placeholder 屬性來提示用戶輸入美食的名字。
配置文本框的 placeholder 文本
-
選中文本框,在實用工具區打開屬性檢查器。
當你點擊檢查器選擇欄第四個按鈕打開屬性檢查器。它能讓你修改 storyboard 中對象的屬性。[圖片上傳失敗...(image-6b2049-1608214722108)]
在屬性檢查器中,找到名為 Placeholder 的區域輸入 Enter meal name。
回車確認,會在文本框中顯示新的 placeholder 文本。
你的場景應該如下:
[圖片上傳失敗...(image-a9e55b-1608214722108)]
當修改文本框屬性的時候,還可以修改選中文本框時彈出的系統鍵盤的屬性。
配置文本框的鍵盤
- 確保文本框仍然是選中狀態。
- 在屬性檢查器中,找到名為 Reture Key 的區域并選擇 Done。
把鍵盤默認的 Return 鍵改成 Done 鍵,意思更加明白。 - 在屬性檢查器中,選中 Auto-enable Return Key 復選框。
這會讓用戶在文本框輸入文本之前不可點擊完成按鈕,確保用戶永遠不會輸入一個空的字符串作為食物的名字。
下一步,在場景的頂部添加一個標簽(UILabel)。標簽不可交互;主要用于在界面中顯示靜態的文本。為了幫助你更好的理解 UI 控件間怎么交互的,請配置標簽來顯示用戶在文本框中輸入的文字。這是很好的方式來測試用戶輸入的文字及對文字進行適當的處理。
往場景中添加標簽
- 在對象庫的搜索框中輸入 label 快速找到標簽。
- 從對象庫中拖動標簽對象放到你的場景中。
- 拖動標簽使其在文本框上方并與場景左邊緣對齊。
當場景像下面這樣停止拖動:
[圖片上傳失敗...(image-90e22d-1608214722108)]
- 雙擊標簽并輸入 Meal Name。
- 回車確認標簽顯示新的文字。
你的場景應該像這樣:
[圖片上傳失敗...(image-ab12-1608214722108)]
往界面中添加按鈕(UIButton)。按鈕可交互,所以用戶可以點擊它來觸發你定義的一個 action。之后,你會創建一個重置標簽文本為默認值的動作。
添加按鈕到你的場景中
在對象庫的搜索框中輸入 buton 快速找到 Button 對象。
從對象庫往你的場景中拖動按鈕。
-
拖動以使其在文本框下方并與場景的左邊緣對齊。
當達到如下效果停止拖動:[圖片上傳失敗...(image-92f072-1608214722108)]
雙擊按鈕輸入 Set Default Label Text。
回車確認在按鈕中顯示了新的文字。
現在,你的場景應該像這樣:
[圖片上傳失敗...(image-2ecb03-1608214722108)]
查看大綱視圖中所有已經添加到你的場景的界面對象,這樣就能更好的理解這些對象如何排列了。
查看大綱視圖
- 在 storyboard 中,找到 outline view toggle。
[圖片上傳失敗...(image-e31927-1608214722108)]
- 如果大綱視圖被折疊了,點擊切換(toggle)按鈕來展開它。
你可以使用 outline view toggle 來折疊和展開大綱視圖。
畫板左邊的大綱視圖能讓你看到 storyboard 中對象分層表示。你應該看到了剛才添加的文本框、標簽和按鈕了,但是為什么這些 UI 對象要嵌套在另一個視圖中?
視圖不止用于屏幕顯示和響應用戶輸入,也可以當做其他視圖的容器。視圖放在一個叫做 view hierarchy 的視圖層次結構中。這個層次結構定義了視圖間的布局關系。在層次中有父視圖和子視圖。一個視圖可以擁有多個子視圖但是只能擁有一個父視圖。
[圖片上傳失敗...(image-5d73a-1608214722108)]
通常每個場景都有自己的視圖層次結構。在視圖層次的頂層是個內容視圖。在當前場景中,這個內容視圖是視圖控制器的頂層視圖。而文本框、標簽和按鈕是它的子視圖。你放置在場景中所有其他視圖都是內容視圖的子視圖(盡管它們自己可以有嵌套的子視圖)
預覽界面
定期預覽 app 來檢查它是否按照你期望的目標來開發。通過使用輔助編輯器來預覽 app 的界面,它是顯示在主編輯器旁邊的第二個編輯器。
預覽界面
點擊 Xcode 右上角工具欄中的 Assistant 按鈕來打開輔助編輯器。
[圖片上傳失敗...(image-2f18e4-1608214722108)]-
點擊 Xcode 工具欄中 Navigator 和 Utilities 按鈕來收縮項目導航和實用工具區,這樣就有更多的工作空間了。
[圖片上傳失敗...(image-5014bb-1608214722108)]
同樣可以收縮大綱視圖。
在輔助編輯器頂部的編輯器選擇欄中,將輔助編輯器從 Automatic 切換為 Preview > Main.storyboard。
[圖片上傳失敗...(image-2dc8a2-1608214722108)]
正如在輔助編輯器中看到的那樣,文本框看起來不太正確。它超過了屏幕的邊界了。在故事板中它看起來是正確的,但為什么在 iPhone 預覽中會出現這種問題呢?
[圖片上傳失敗...(image-25aa88-1608214722108)]
這時候需要為不同尺寸的 iPhone 和 ipad 屏幕構建一個自適應界面。例如,當界面縮小到 iPhone 屏幕大小,文本框應該收縮。當界面變成 ipad 屏幕大小,文本框應該更長。您可以使用自動布局來指定這些規則。
使用自動布局(Auto Layout)
自動布局是一個功能強大的布局引擎,它可以幫助您設計自適應界面。向它表達你的意圖來描述場景中對象的位置,然后讓布局引擎決定如何最好地實現這一意圖。使用約束規則來描述你的意圖,說明一個對象相對于另一個的位置,它應該是什么大小,當布局空間減少了這兩個對象應該收縮。
與自動布局相結合,有一個很有用的工具就是堆棧視圖(UIStackView)。用于在一個列或行中放置布局對象的集合。它能充分利用自動布局的力量,創建動態適應設備方向、屏幕大小和可用空間變化的用戶界面。
您可以輕松地將現有的界面加入堆棧視圖中,添加必要的約束,以使堆棧視圖在不同的情況下顯示正確。
為食物場景添加自動布局約束
-
點擊 Standard 按鈕返回標準編輯器。
[圖片上傳失敗...(image-152ed9-1608214722108)]
點擊 Navigator 和 Utilities 按鈕展開項目導航和實用工具區。
-
按住鍵盤的 Shift 鍵,選中文本框、標簽和按鈕。
[圖片上傳失敗...(image-4c1fc5-1608214722108)]
-
在畫板的底部,單擊 Stack 按鈕。(或者選擇 Editor > Embed In > Stack View)。
[圖片上傳失敗...(image-9b9672-1608214722108)]
Xcode 將 UI 控件堆疊在堆棧視圖中并分析布局算出所有項應該垂直而不是水平堆疊。
[圖片上傳失敗...(image-448db6-1608214722108)]
-
打開大綱視圖。選擇 Stack View 對象。
[圖片上傳失敗...(image-e5096d-1608214722108)]
-
在屬性檢查器的 Spacing field 中輸入 12?;剀嚧_認。
你會注意到垂直方向拉開了一些距離,以及與它們一起變長的堆棧視圖[圖片上傳失敗...(image-561741-1608214722108)]
-
打開畫板右下角的 Pin 菜單。
[圖片上傳失敗...(image-d23382-1608214722108)]
-
點擊菜單中
Spacing to nearest neighbor
上面的兩個橫向約束和垂直 top 約束來選中它們。當約束被選中就會變紅。[圖片上傳失敗...(image-7883c2-1608214722108)]
這些約束表明間距最近的 leading、trailing、以及 top 邊界的間距。術語 "nearest neighbor" 意思是最近的 UI 對象的邊界,UI 對象可以是父視圖或同級視圖。因為 “Constrain to margins” 復選框被選中,堆棧視圖將與它父視圖的左、右和頂部邊界有額外8個點的間距。
在左、右框中輸入0,在頂部框中輸入60的間隙。
-
在 Update Frames 旁邊的彈出菜單中,選擇 Items of New Constraints 。
Pin menu 應該像這樣:[圖片上傳失敗...(image-1e8876-1608214722108)]
-
在 Pin 菜單中,點擊 Add 3 Constraints 按鈕。
[圖片上傳失敗...(image-34c9cd-1608214722108)]
最后的場景 UI 應該像這樣:
[圖片上傳失敗...(image-a56c1c-1608214722108)]
你會注意到,文本框并沒有像之前那樣超過場景的邊界了。
調整場景文本框的寬度
選擇 storyboard 中食物場景的文本框。
-
打開畫板右下角的 Pin 菜單。
[圖片上傳失敗...(image-6d5a0a-1608214722108)]
點擊
Spacing to nearest neighbor
上面的兩個水平約束來選中它們。當選中后它們變成紅色。在左右框中輸入0。
-
在 Update Frames 旁邊的彈出框中,選擇 Items of New Constraints。
Pin 菜單應該像這樣:[圖片上傳失敗...(image-1b8efd-1608214722108)]
-
在 Pin 菜單中,點擊 Add 2 Constraints 按鈕。
[圖片上傳失敗...(image-a7c33e-1608214722108)]
-
選中文本框,在實用工具區打開尺寸檢查器。
點擊檢查器欄第五個按鈕打開尺寸檢查器。它能讓你編輯 storyboard 中控件的尺寸和位置。[圖片上傳失敗...(image-8c1581-1608214722108)]
-
在 Intrinsic Size 區域,選擇 Placeholder(這個區域在尺寸檢查器的底部,所以你需要滾動才能看到它。)。
文本框的尺寸基于它的內容,而內容定義了它的固有內容尺寸(intrinsic content size)。固有內容尺寸是指顯示視圖所有內容所需的最小尺寸。現在,文本框的內容僅是其占位字符串,但是用戶實際輸入的內容有可能比它長。食物場景界面應該像這樣:
[圖片上傳失敗...(image-2bc54e-1608214722108)]
檢驗:在模擬器中運行你的 app。文本框不再超過屏幕的邊界了。點擊文本框并使用鍵盤輸入一些文本(通過按 Command-K 切換軟鍵盤)。如果旋轉設備( Command-左箭頭 或 Command-右箭頭)或在不同設備上運行 app,文本框會按照設備方向和屏幕尺寸縮放到合適的大小。注意,在橫屏方向上狀態欄消失了。
[圖片上傳失敗...(image-9cd6dc-1608214722108)]
如果沒有得到你期望的效果,請使用自動布局調試功能。單擊 Resolve Auto Layout Issues 圖標,并選擇 Reset to Suggested Constraints 讓 Xcode 使用默認的約束來更新界面?;騿螕?Resolve Auto Layout Issues 圖標,并選擇 Clear Constraints 來刪除界面對象的所有約束,然后再一次按照之前的步驟來設置約束。
[圖片上傳失敗...(image-80700c-1608214722108)]
注意:
為了看到本課的完整示例項目,下載文件并在 Xcode 中查看它。