本章,你將鏈接FoodTracker應用程序的UI到代碼並定義一些可執行的動做。當你完成時,你的應用程序將是這個樣子:編程
學習目標
在課程結束時,你將可以:
1.解釋一個storyboard中的場景和view controller之間的關係
2.在storyboard中UI元素和源代碼建立出口和鏈接動做
3.從文本字段處理用戶輸入並在UI中顯示結果
4.使用一個類遵循一個協議
5.理解委託設計模式
6.在設計應用程序體系結構時,按照目標 - 動做模式swift
鏈接UI到源代碼設計模式
在storyboard的元素連接到源代碼。重要的是要了解storyboard和你寫的代碼之間的關係。在storyboard中,一個場景表明的一個內容屏,一般一個視圖控制器。視圖控制器實現您的應用程序的行爲。視圖控制器管理單個內容視圖和編輯器
它的子子視圖的層次。視圖控制器在應用程序的數據模型之間協調信息流,它封裝應用程序的數據,而且顯示數據,管理其內容視圖的生命週期,該設備被旋轉時,處理方向改變,定義應用程序的導航,並響應用戶輸入的行爲。在全部的ide
iOS視圖控制器對象類型爲UIViewController或其子類。經過建立和實現自定義視圖控制器子類來在代碼中定義您的視圖控制器的行爲。而後,您能夠建立你的storyboard,讓你在代碼中定義的行爲,你在storyboard中定義的UI,並性能
把這些類和場景鏈接起來。Xcode中已經建立了這樣一個類,就是ViewController.swift,並將在storyboard中其鏈接到你工做的場景。在將來,當你添加更多的場景,你能夠經過Identity inspector來連接。Identity inspector能夠學習
在storyboard中編輯,你能夠指定某個類和storyboard關聯起來測試
在運行時,你的storyboard將會建立一個ViewController的實例,你自定義的視圖控制器的子類。你在APP中看到的屏幕會在場景中顯示UI定義並在ViewController.swift中定義行爲。雖然場景鏈接到了ViewController.swift,這不是須要作的惟一的鏈接。要和你的APP互動,你的視圖控制器源代碼須要能和View溝通。在storyboard中的view和視圖控制器源代碼文件之間,你經過定義額外的鏈接,如調用出口和動做動畫
建立UI元素出口ui
出口(Outlet)提供一個方法來引用界面對象,前提是這些對象已經在你的storyboard中。爲了建立一個outlet,在storyboard中從一個指定對象控制拖動到一個視圖控制器文件。這個操做會爲你視圖控制器文件中的對象建立一個屬性,這個屬性能讓你在運行時的代碼中訪問和操做對象。你須要爲文本框和標籤建立outlets來引用它們,步驟以下:
1.打開你的storyboard,Main.storyboard
2.點擊Assistant按鈕打開assistant editor,它在Xcode的頂部右邊
3.若是你想要更多空間,你能夠摺疊navigator,utility和outlin 區域,
4.在editor selector bar中頂部出現的assistant editor,從Preview改爲Automatic > ViewController.swift
5.打開ViewController.swift類,添加一行註釋// MARK:
6.在storyboard中,選擇文本框
7.按下Control的同時拖動畫布中的文本框到代碼中,在註釋那一行中止拖動。以下圖所示:
8.在彈出的對話框中,的Name字段後,輸入nameTextField,而後就能夠了,以下圖所示:
IBOutlet屬性告訴Xcode,你能從Interface Builder鏈接到
nameTextField屬性(這就是爲何屬性前綴爲IB)。weak關鍵字表示這個屬性可能沒有值(nil)。nameTextField表示聲明一個
UITextField類的變量,末尾的感嘆號表示它是一個可選也能夠是非可選的值,不須要每次訪問時,展開這個可選值,由於他假定老是有一個初始化的值,如今以相同的方式把標籤也鏈接到代碼。
@IBOutlet weak var mealNameLabel: UILabel!
定義要執行的動做(Action)
iOS應用程序都是基於事件驅動編程。系統事件和用戶動做:即,應用程序的流由事件決定。用戶在界面中執行動做來觸發的應用程序的事件。這些事件致使應用程序執行邏輯和操做它的數據。該應用程序的響應用戶的操做,而後反射回UI中。因爲用戶,而不是開發者,用戶只會觸發一些動做,但到底哪些動做你想處理,你就能夠寫對應的動做處理代碼。通常對於用戶的動做,咱們須要友好的響應。一個動做(或動做方法)是一段代碼,它能夠鏈接到發生在你應用程序中的事件。當該事件發生時,代碼被執行。你能夠定義一個操做方法,從操縱一個數據來更新UI。你使用動做來驅動APP的流程,爲了響應用戶或系統事件。你建立一個outlet,就是以一樣的方式建立一個動做:在你的storyboard中,Ctrl+拖動一個特定的對象打牌視圖控制器文件中。此操做會在你的視圖控制器的文件中建立方法,當用戶和對象交互時,動做的方法會被觸發。首先建立一個簡單的動做,當用戶點擊Set Default Label Text按鈕時,設置標籤的值爲Default Text,接下來讓咱們寫這個動做:
1.在最後一個大括號的前面寫下以下注釋
// MARK: Actions
這個註釋表示這段代碼會執行動做
2.在你的 storyboard中,選擇Set Default Label Text按鈕
3.按住Control鍵拖動畫布中的按鈕到右邊的編輯器中的代碼上,在你尷剛纔註釋的代碼上中止拖動
4.早彈出的對話框中的Connection字段右邊選擇Action
5.Name字段右邊,鍵入setDefaultLabelText
6.Type字段右邊,選擇UIButton
你可能注意到Type的默認值是AnyObject,在Swift中AnyObject是一個類型,它用於描述一個能夠輸入任意類的對象。指定動做的類型爲UIButton意思是僅僅只有按鈕對象能鏈接到這個動做。雖然對你如今建立的動做沒有意義,但記住它是頗有必要的,未來會用到,這時你的對話框應該以下圖所示:
7.點擊connect
Xcode會添加代碼到你的ViewController.swift中
@IBAction func setDefaultLabelText(sender: UIButton) {
}
sender參數指向觸發動做的對象,當前狀況下是一個按鈕。IBAction屬性是表示這個方法是一個動做,你能從storyboard中鏈接到Interface Builder。剩餘的
setDefaultLabelText只是一個方法名。如今方法體中沒有代碼,實現重置標籤的代碼是很簡單的。下面讓咱們來實現這個動做:
a.在ViewController.swift中找到你剛添加的setDefaultLabelText動做方法
b.在方法中實現以下代碼:
@IBAction func setDefaultLabelText(sender: UIButton) { mealNameLabel.text = "Default Text" }
你可能猜到了,這個代碼是設置標籤文本的默認屬性。text是標籤對象中的屬性。注意,你沒必要指定默認文本的類型,由於Swift中能夠正確類型推斷出它的類型。
檢查點:測試你的代碼,運行模擬器。當你單擊Set Default Label Text按鈕時,標籤會從Meal Name變成Default Text。
你剛纔實現的行爲是在iOSAPP設計target-action模式的一個例子。target-action設計是當特定事件發生時的其中一個對象將消息發送給另外一個對象。在本例中,該事件是用戶輕敲Set Default Label Text按鈕,動做是setDefaultLabelText方法,目標的ViewController(定義動做方法的地方),而發送者是Set Default Label Text按鈕。該消息是在源代碼中定義的方法,目標是接收消息的對象,同時它也是一個可以執行動做的對象。發送動做消息的對象一般是一個按鈕,滑塊,或開關,能夠響應於用戶交互動做,如點擊,拖動。這種模式在iOS應用程序中很是廣泛的,你會在後面看到更多。
處理用戶輸入
在這一點上,你必須有一個能從新設置標籤的默認值的一種方式,而如今你已經會添加行爲,來設置文本框的值。爲了簡單起見,你會依賴於用戶點擊文本框鍵盤上的Return 鍵的動做,指示標籤將會更新。
當您從文本框接受用戶輸入時,則須要從文本框委託一些幫助。委託是一個表明動做的對象,或另外一個對象協調配合。在這種狀況下的委託對象是文本框,委託對象將消息發送到委託。該消息告訴該委託有關該委託對象將要處理或剛處理的事件。委託能夠響應由例如,更新對象外觀或狀態,能夠是自身也能夠是其餘對象,或返回一個值,該值做用於一個即將到來的事件的處理方式。
當文字被編輯時,文本框的委託和文本框進行通訊,而且知道在重大事件發生時,好比當用戶開始或中止編輯文本。委託能夠在正確的時間使用這些信息來保存或清除數據,消除鍵盤,等等。
任何對象能夠做爲另外一個對象的委託,由於它符合適當的協議。它定義了一個文本框的委託協議,被稱爲UITextFieldDelegate。在這種狀況下,因爲ViewController保持了一個文本框的引用,因此你會讓ViewController成爲文本框的委託。
首先,你須要有采用UITextFieldDelegate協議的ViewController。你能夠經過將其列爲類中的一行代碼來聲明採用一個協議。下面讓咱們來看看UITextFieldDelegate協議是如何分配的
1.返回standard editor
2.在項目導航中,選擇ViewController.swift文件
3. ViewController.swift找到class這一行,以下所示:
class ViewController: UIViewController {
4.在UIViewController後,添加逗號和UITextFieldDelegate表示採用這個協議:
lass ViewController: UIViewController, UITextFieldDelegate {
經過採用該協議。這意味着你設置了文本框的委託,能夠實現它的一些行爲來處理文本框的用戶輸入。
接下來咱們爲nameTextField設置ViewController做爲一個委託
a.在ViewController.swift中,找到viewDidLoad()方法:
override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. }
該模板此方法的實現,會自動生成註釋。你能夠刪除註釋。
b.在super.viewDidLoad()下面添加一行代碼
// Handle the text field’s user input through delegate callbacks. nameTextField.delegate = self
self表示ViewController本身。如今
ViewController是一個爲nameTextField服務的委託
UITextFieldDelegate協議包含了可選的方法,這表示你沒必要實現它們。但你能夠得到你想要的指定的行爲,你能夠還實現這兩個方法
func textFieldShouldReturn(textField: UITextField) -> Bool
func textFieldDidEndEditing(textField: UITextField)
爲了理解當這些方法的調用時,他們須要作什麼,重要的是知道文本框如何響應用戶事件,當用戶點擊文本框,會自動變成首要響應對象。在APP中首要響應對象是首先響應APP事件的對象,包括鍵盤事件,手勢事件,動做消息等。換句話說,許多由用戶生成的事件最初都會連接到首要響應
做爲文本框變成首要響應事件的結果,iOS顯示鍵盤並開始爲文本框編輯會話。經過鍵盤來鍵入類容到文本框中
當一個用戶想要完成文本框的輸入時,文本框須要放棄首要響應狀態。由於文本框再也不是APP的當前對象,事件須要傳遞到更合適的對象中
這是實現UITextFieldDelegate進入方法的地方。當用戶點擊按鈕來結束編輯時,你須要指定文本框放棄它的首要響應狀態。你能夠在textFieldShouldReturn()方法中這麼作,它表示當用戶在軟鍵盤上點擊Return後的調用。
下面讓咱們來實現UITextFieldDelegate協議的textFieldShouldReturn()方法
a.打開ViewController.swift
// MARK: UITextFieldDelegate
該註釋用於組織你的代碼,並幫助你(和其餘讀你代碼的人)導航。
您已經添加了幾個這樣的註釋了。 Xcode中列出了全部這些註釋,做爲源代碼文件的functions menu中的標題,若是你單擊該標題。你的代碼快速跳轉到一個地方。你會發現跳轉到了// MARK:注意冒號必須打
b.在註釋下方,添加方法
func textFieldShouldReturn(textField: UITextField) -> Bool {
}
c.在方法中,添加以下代碼來放棄文本框的首要響應狀態。
// Hide the keyboard. textField.resignFirstResponder()
當你輸入res的時候,Xcode強大的代碼完成功能,會讓你寫代碼更快,相似Eclipse等須要軟件都自帶這個強大省時的功能。
d.在方法中,添加以下代碼:
return true
由於這個方法返回一個布爾值,返回true表示文本框將響應用戶按下的返回鍵來讓軟鍵盤消失
你的textFieldShouldReturn方法看起來會是這樣:
func textFieldShouldReturn(textField: UITextField) -> Bool { // Hide the keyboard. textField.resignFirstResponder() return true }
第二個方法是textFieldDidEndEditing(),它在textFieldShouldReturn()以後調用。
textFieldDidEndEditing()方法給你一個機會讀取輸入到文本框中的信息,並用它作些什麼。在本例中,咱們會用文本框中的文原本改變你的標籤的值。
func textFieldDidEndEditing(textField: UITextField) { mealNameLabel.text = textField.text }
檢查點:測試你的代碼,運行模擬器。您能夠選擇文本框,並輸入文本。當你點擊鍵盤上的Done 按鈕,鍵盤消失,標籤文字會變成文本框中的文本。當你單擊 Set Default Label Text按鈕時,標籤會顯示Default Text