連接界面(UI)到代碼中
本文中將講述連接FoodTracker應(yīng)用的界面元素到程序代碼中,定義一些用戶能夠在界面上執(zhí)行的動(dòng)作。
本文的學(xué)習(xí)目標(biāo)
- 解釋storyboard中一個(gè)scene和底層視圖控制器(view controller)之間的關(guān)系
- storyboard上界面元素和源代碼之間創(chuàng)建outlet和action的連接
- 處理用戶在文本輸入框的輸入,在界面上顯示結(jié)果
- 設(shè)計(jì)遵循一個(gè)協(xié)議的類
- 理解代理(delegation)模式
- 根據(jù)目標(biāo)-動(dòng)作(target-action)模式設(shè)計(jì)應(yīng)用的架構(gòu)
連接界面到源代碼
在storyboard中,一個(gè)場(chǎng)景(scene)一般代表一個(gè)視圖控制器(view controller),視圖控制器實(shí)現(xiàn)了應(yīng)用程序的行為。一個(gè)視圖控制器管理著單個(gè)內(nèi)容視圖及其具有繼承關(guān)系的子視圖,協(xié)調(diào)應(yīng)用程序數(shù)據(jù)模型(封裝了應(yīng)用的數(shù)據(jù))信息的流向并在視圖上顯示數(shù)據(jù),管理內(nèi)容視圖的生命周期,處理設(shè)備旋轉(zhuǎn)產(chǎn)生的方向變化,定義應(yīng)用程序中的界面導(dǎo)航,實(shí)現(xiàn)用戶輸入的響應(yīng)行為。iOS中所有視圖控制器對(duì)象都是UIViewController類或其子類。
代碼中創(chuàng)建并實(shí)現(xiàn)自定義視圖控制器的子類,建立類和storyboard中的場(chǎng)景之間的連接,關(guān)聯(lián)代碼中的行為到storyboard中的界面。
上一節(jié)的項(xiàng)目中,Xcode自動(dòng)創(chuàng)建了定義ViewController類的swift源代碼文件(ViewController.swift),并已連接到storyboard對(duì)應(yīng)的一個(gè)視圖場(chǎng)景。使用Identity Inspector編輯storyboard上界面元素的對(duì)象屬性,例如所從屬的類。

根據(jù)界面元素創(chuàng)建Outlets
打開(kāi)主storyboard;
-
點(diǎn)擊右上角的助手編輯器;
assistant_editor_toggle_2x.png -
在編輯選擇欄選中預(yù)覽ViewController.swift;
3_switchtoviewcontroller_2x.png -
在ViewController.swift代碼中找到類的定義行;
class ViewController: UIViewController { -
在定義行下面添加MARK注釋行;
// MARK: Properties
帶有“// MARK:”開(kāi)頭的注釋是一種特殊的注釋,用于組織代碼和幫助導(dǎo)航到此處代碼
-
在storyboard界面上選中文本輸入框,按住Control鍵的同時(shí)鼠標(biāo)拖拽至ViewController.swift文件中“// MARK: Properties”代碼下面;
![Uploading 3_textfield_addoutlet_2x_321850.png . . .]
3_textfield_dragoutlet_2x.png -
在出現(xiàn)的對(duì)話框中Name欄中輸入nameTextField;
3_textfield_addoutlet_2x.png - 點(diǎn)擊“Connect”按鈕。
@IBOutlet weak var nameTextField: UITextField!
Xcode將增加一個(gè)用于指向文本對(duì)話框的相應(yīng)代碼到ViewController.swift文件中,并配置storyboard建立上述連接。
IBOutlet屬性通知Xcode從界面編輯器(Interface Builder,前綴縮寫(xiě)IB)中連接到一個(gè)叫“nameTextField”的屬性,weak關(guān)鍵字表明該屬性有可能為nil,這個(gè)屬性類型為UITextField,其最后的“!”是隱式解包可選類型。
連接標(biāo)簽到ViewController.swift代碼中
-
選中storyboard中的標(biāo)簽對(duì)象,按住Control鍵的同時(shí)鼠標(biāo)拖拽至ViewController.swift代碼文件中聲明nameTextField屬性的代碼下面;
3_label_dragoutlet_2x.png -
在出現(xiàn)的對(duì)話框中Name欄中輸入mealNameLabel;
3_label_addoutlet_2x.png - 點(diǎn)擊“Connect”按鈕。
同樣,Xcode將增加一個(gè)用于指向標(biāo)簽的相應(yīng)代碼到ViewController.swift文件中,并配置storyboard建立上述連接,同文本輸入框?qū)傩砸粯?,只是屬性名稱叫“mealNameLabel”,類型是UILabel。@IBOutlet weak var mealNameLabel: UILabel!
定義一個(gè)要執(zhí)行的動(dòng)作(Action)
iOS應(yīng)用程序是基于事件驅(qū)動(dòng)編程(event-driven programming),即應(yīng)用程序的執(zhí)行流向是由事件決定:系統(tǒng)事件和用戶動(dòng)作。用戶在界面上執(zhí)行動(dòng)作觸發(fā)應(yīng)用程序內(nèi)的事件,這些事件導(dǎo)致應(yīng)用程序的邏輯執(zhí)行和數(shù)據(jù)處理操作,應(yīng)用程序?qū)τ脩魟?dòng)作的響應(yīng)最終反映到界面中。
動(dòng)作(Action)是一個(gè)代碼片段,可以連接到出現(xiàn)在應(yīng)用程序上的某個(gè)事件。當(dāng)該事件發(fā)生時(shí),這些代碼得到執(zhí)行。定義一個(gè)動(dòng)作方法完成各種事務(wù),如操作一個(gè)數(shù)據(jù)塊或者更新界面等。使用動(dòng)作響應(yīng)用戶或系統(tǒng)的事件,來(lái)驅(qū)動(dòng)應(yīng)用程序的執(zhí)行流。創(chuàng)建一個(gè)動(dòng)作類似于創(chuàng)建一個(gè)outlet。
創(chuàng)建一個(gè)標(biāo)簽重置動(dòng)作(reset action)
- 在ViewController.swift類定義塊“}”添加MARK Action注釋代碼;
// MARK: Actions -
在storyboard中選中“設(shè)置缺省標(biāo)簽文字”按鈕,按住Control鍵的同時(shí)鼠標(biāo)拖拽至MARK Action注釋代碼下面;
3_button_dragaction_2x.png - 在出現(xiàn)的對(duì)話框中,Connection欄選擇Action;
- Name欄中輸入“setDefaultLabelText”;
-
Type欄選擇UIButton;
3_button_addaction_2x.png - 點(diǎn)擊“Connection”按鈕。
Type欄的缺省為AnyObject,Swift語(yǔ)言中AnyObject表明一個(gè)可以屬于任何類的對(duì)象類型。Xcode將增加一段代碼到ViewController.swift文件中,并配置動(dòng)作方法。
> `@IBAction func setDefaultLabelText(sender: UIButton) {
}`
上面代碼中,sender參數(shù)指向的對(duì)象導(dǎo)致觸發(fā)了動(dòng)作,本例是“設(shè)置缺省標(biāo)簽文字”按鈕。IBAction屬性表明本方法是一個(gè)從storyboard界面上連接的動(dòng)作。
代碼實(shí)現(xiàn)標(biāo)簽重置動(dòng)作
- 在ViewController.swift找到剛才添加的setDefaultLabelText動(dòng)作方法;
- 添加一行代碼。
mealNameLabel.text = "Default Text"
上面完成的例子實(shí)現(xiàn)了iOS應(yīng)用程序設(shè)計(jì)中的”目標(biāo)-動(dòng)作”(target-action)模式,該模式用于當(dāng)一個(gè)指定事件發(fā)生時(shí)一個(gè)對(duì)象發(fā)送消息到另一個(gè)對(duì)象。本例中,這個(gè)事件是用戶點(diǎn)擊“設(shè)置缺省標(biāo)簽文字”按鈕,動(dòng)作是setDefaultLabelText,目標(biāo)是ViewController(動(dòng)作方法所在的類),發(fā)送著是“設(shè)置缺省標(biāo)簽文字”按鈕。”目標(biāo)-動(dòng)作”模式中,消息是在代碼中定義的一個(gè)動(dòng)作方法,目標(biāo)(target)是接收消息的對(duì)象-能夠執(zhí)行該動(dòng)作的對(duì)象,發(fā)送動(dòng)作消息的對(duì)象通常是一個(gè)控件(control),例如按鈕、滑桿(slider)、切換器(switch)等-觸發(fā)相應(yīng)的事件:點(diǎn)擊、拖拽或數(shù)值改變等。
處理用戶輸入
當(dāng)處理接收用戶在一個(gè)文本輸入框的輸入時(shí),需要用到文本輸入框代理(delegate)的一些幫助。當(dāng)文本輸入框的文本發(fā)生變化時(shí)或者發(fā)生重要事件如用戶開(kāi)始或終止編輯文本,會(huì)與其代理進(jìn)行通信,代理可以使用這些信息在合適的時(shí)機(jī)保存或清除數(shù)據(jù),關(guān)閉鍵盤(pán)屏幕等。任何對(duì)象作為另外一個(gè)對(duì)象的代理相當(dāng)于其遵從適應(yīng)的協(xié)議,一個(gè)定義文本輸入框代理的協(xié)議名為UITextFieldDelegate,本例因?yàn)閂iewController保持文本輸入框的一個(gè)引用,將其作為文本輸入框的代理,ViewController類采用UITextFieldDelegate協(xié)議。
采用UITextFieldDelegate協(xié)議
- 在ViewController.swift文件中找到class定義行;
- 使用”,”符號(hào)添加采用UITextFieldDelegate聲明。
class ViewController: UIViewController, UITextFieldDelegate {
設(shè)置ViewController為文本輸入框nameTextField的代理
- 在ViewController.swift文件中找到viewDidLoad()方法;
- 在代碼行super.viewDidLoad()后面,添加下面代碼。
nameTextField.delegate = self
self關(guān)鍵字引用ViewController類本,ViewController類就成為文本輸入框nameTextField的代理。
實(shí)現(xiàn)UITextFieldDelegate協(xié)議方法
UITextFieldDelegate協(xié)議包含選項(xiàng)方法,采用該協(xié)議的類可以不提供選項(xiàng)方法的實(shí)現(xiàn),本例為了完成一些行為,提供實(shí)現(xiàn)下面兩個(gè)方法的實(shí)現(xiàn)。
func textFieldShouldReturn(textField: UITextField) -> Bool func textFieldDidEndEditing(textField: UITextField)
當(dāng)用戶點(diǎn)擊一個(gè)文本輸入框時(shí),該輸入框自動(dòng)成為一個(gè)首響應(yīng)者(first responder),第一個(gè)接收各種類型的應(yīng)用事件,包括按鍵事件、移動(dòng)事件和動(dòng)作消息等。 文本輸入框成為首響應(yīng)者的一個(gè)結(jié)果就是,iOS系統(tǒng)會(huì)顯示鍵盤(pán)小窗口,輸入框開(kāi)始一個(gè)編輯事務(wù)。當(dāng)用戶想要完成文本輸入框的編輯,該輸入框需要退出首響應(yīng)者狀態(tài)。因此上面兩個(gè)協(xié)議方法的實(shí)現(xiàn),會(huì)用于這個(gè)情況:用戶點(diǎn)擊一個(gè)按鈕來(lái)結(jié)束文本輸入框的編輯,這里用戶點(diǎn)擊“完成”(Done)或“返回”(Return),協(xié)議方法textFieldShouldReturn(_:)會(huì)被調(diào)用。
實(shí)現(xiàn)textFieldShouldReturn方法
-
在ViewController.swift文件中"http://MARK:Actions"上面添加MARK注釋代碼如下
// MARK: UITextFieldDelegate -
在下面輸入“func textfieldS”會(huì)出現(xiàn)自動(dòng)完成列表,顯示推薦的方法,選擇textFieldShouldReturn方法;
func textFieldShouldReturn(textField: UITextField) -> Bool { } -
在textFieldShouldReturn方法中添加以下代碼。
textField.resignFirstResponder() return true -
完整的代碼如下。
func textFieldShouldReturn(textField: UITextField) -> Bool { textField.resignFirstResponder() return true }
調(diào)用UITextField的resignFirstResponder方法退出首響應(yīng)者狀態(tài),返回true表明文本輸入框響應(yīng)用戶點(diǎn)擊Return按鍵后關(guān)閉鍵盤(pán)小窗口。
實(shí)現(xiàn)textFieldDidEndEditing方法
文本輸入框退出首響應(yīng)者狀態(tài)后,會(huì)調(diào)用textFieldDidEndEditing協(xié)議方法。
- 在ViewController.swift文件中,找到textFieldShouldReturn方法;
- 在其下面添加以下方法和代碼。
func textFieldDidEndEditing(textField: UITextField) { mealNameLabel.text = textField.text }
運(yùn)行模擬器








