Start Developing iOS Apps (Swift)->将UI连接到代码(二)

处理用户输入

现在,用户可以重置菜品名称label的默认值,但是你真正想要的是让用户使用text filed来输入他们自己的菜品名。为了简单起见,让用户在text field中输入文本,然后点击回车键,更新mealNameLabel对象的text属性值。

当要接收来自text filed的用户输入的时,你需要一些来自text field delegate的帮助。Delegate(代理)是一个代表另一个对象或与另一个对象协同工作的对象。委托对象(在本例中为text field)保留另一个代理对象(代理,delegate)的引用,并且在适当的时候,这个委托对象会发送一个消息给代理。这条消息告诉代理关于委托对象要处理或者刚刚处理的事件。代理可以作出响应,例如,更新自身或者其他对象的外观或状态,或者返回一个值,这个值会影响一个即将到来的事件会被如何处理。

当用户编辑文本的时候,text filed的delegate会和text field进行通信,并且知道重要的事件何时发生,例如用户何时开始或结束编辑文本。Delegate可以使用这些信息在合适的时候保存或清除数据、移除键盘等等。

任何对象都可以成为另一个对象的代理,只要它遵守合适的协议(protocol)。定义了text filed代理方法的协议称为UITextFieldDelegate。使用视图控制器作为它管理的对象的代理是很常见的。在本例中,你将使用ViewController实例作为text filed的代理。

首先,ViewController需要遵守UITextFieldDelegate协议。只要把协议列在类声明行里既可以表示遵守了协议。

采用UITextFieldDelegate协议

  1. 如果助理视图还开着,点击Standard按钮回到标准编辑器。


    image: ../Art/standard_toggle_2x.png
  2. 在Xcode工具条中点击Navigator和Utilities按钮展开project navigator和utility area。
  3. 在project navigator,选择ViewController.swift。
  4. 在ViewController.swift,找到class行,它看上去是这样的:
class ViewController: UIViewController {
  1. 在UIViewController后 main,添加一个逗号(,)和UITextFieldDelegate来遵守协议。
class ViewController: UIViewController, UITextFieldDelegate {

通过遵守UITextFieldDelegate协议,你告诉了编译器ViewController类会作为有效的text filed 的代理来做事。这意味着,你可以实现协议的方法来处理文本输入,并且可以指定ViewController类的实例作为text field的代理。

设置ViewController对象作为它的nameTextField属性的代理

  1. 在ViewController.swift中,找到viewDidLoad()方法,它看上去是这样的:
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
}

这个方法的模版实现包含一个注释。你不需要这个注视,先删掉它。

  1. 在super.viewDidLoad()的下方,空一行然后添加下面这段代码:
// Handle the text field’s user input through delegate callbacks.
nameTextField.delegate = self

self指向ViewController类,这是因为它只在ViewController类定义的范围内被引用。你可以添加自己的注释来帮助理解代码的作用。

现在viewDidLoad()方法看上去是这样的:

override func viewDidLoad() {
    super.viewDidLoad()
            
    // Handle the text field’s user input through delegate callbacks.
    nameTextField.delegate = self
}

当ViewController实例被加载时,它设置它自己作为属性nameTextField的代理。

UITextFieldDelegate协议定义了八个可选方法。只需要实现那些你想要的行为即可。这儿,你需要实现下面两个方法:

func textFieldShouldReturn(_ textField: UITextField) -> Bool
func textFieldDidEndEditing(_ textField: UITextField)

为了理解这些方法何时被调用以及它们需要做什么,则需要了解text field如何响应用户的行为。当用户点击text field的时候,它自动成为第一响应者。在一个应用中,第一响应者(first responder)是一个排在首位去接收各种应用事件的对象,包括键盘事件、运动时间、以及action消息等等。换句话说,很多用户产生的事件最初都要路由给第一响应者。

作为text field成为第一响应者的结果,iOS显示了键盘,并且text field开始了编辑会话。用户使用键盘输入的内容被插入到了text field中。

当用户想结束text field编辑,text field需要注销它的第一响应者状态。因为text filed将不再是应用的活动对象,事件需要被路由到其他更合适的对象。

这时就需要实现UITextFieldDelegate方法了。当用户点击按钮结束text filed的编辑时,你必须让text field注销它的第一响应者状态。你要在textFieldShouldReturn(_:)方法里做这些,这个方法会在用户点击键盘上的Return(或者像本例中的,Done)按钮时被调用。

实现UITextFieldDelegate协议的textFieldShouldReturn(_:)方法

  1. 在ViewController.swift中,在// MARK: Actions部分的上面,添加下面这个注释:
//MARK: UITextFieldDelegate

这个注释用来组织你的代码,并帮助你(以及任何读你代码的人)导航它。
迄今你已经添加了好几个这样的注释。Xcode会在源码文件的函数菜单(Functions menu) 菜单中将这些注释罗列为每一部分的标题,这个列表会在你点击编辑区域顶部的文件名的时候出现。函数菜单让你可以在代码中快速跳到特定部分。你注意到这些部分是你之前用//MARK:标记的。点击一个部分的标题就可以跳到文件中的相应部分。


image: ../Art/CUIC_functionsmenu_2x.png

2 在注释的下面,添加下面这个方法:

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
}       

3 在这个方法中,添加下面的方法来注销text filed的第一响应者状态,并且添加一个注释来描述这段代码所做的事:

// Hide the keyboard.
textField.resignFirstResponder()

尝试键入第二行代码而不是复制粘贴。你将发现代码补全(code completion)是一个可以大大节约时间的Xcode功能。当Xcode带有潜在的补全列表时,滚动这个列表直到找到你想要的那个然后按下回车键。Xcode会为你把整行插入。


image: ../Art/CUIC_code_completion_2x.png

4 在这个方法中,添加下面这行代码:

return true

这个方法返回一个布尔值来表明是否系统应该处理按下Return键的行为。在本例中,你始终要响应用户按下Return键,所以要键入true。

现在你的textFieldShouldReturn(_:)方法应该是这个样子了:

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
     // Hide the keyboard.
    textField.resignFirstResponder()
    return true
}

你需要实现的第二个方法,textFieldDidEndEditing(_:),它在text field注销了它的第一响应者状态的时候被调用。因为你是在textFieldShouldReturn方法中注销第一响应者状态的,所以系统调用者个方法是调用textFieldShouldReturn发发之后紧接着进行的。

textFieldDidEndEditing(_:)方法给了你一个机会来读取在text field中输入的信息以及对这些信息进行操作。在本例中,你将获取text field中的文本并用它修改你的label的值。

实现UITextFieldDelegate协议的textFieldDidEndEditing(_:)方法

  1. 在ViewController.swift中,在textFieldShouldReturn(_:)方法后面,添加如下方法:
func textFieldDidEndEditing(_ textField: UITextField) {
}
  1. 在这个方法中,添加下面这行代码:
mealNameLabel.text = textField.text

你只需做这些就能看到结果了。你的textFieldDidEndEditing(_:)方法看上去应该如下:

func textFieldDidEndEditing(_ textField: UITextField) {
    mealNameLabel.text = textField.text
}

检查点:运行模拟器来测试你的改变。你能选择text field并键入文本。当你点击Done按钮的时候,键盘会缩回,并且label的文本变为现实在text field上的文本。当你点击Set Defautl Label Text 按钮的时候,这个label显示的文字从当前的文字变成Default Text(这个值你之前设置在了action方法里)。

image: ../Art/CUIC_sim_finalUI_2x.png

小结

在本课中,你使用了助理编辑器添加outlets和actions到你的源代码。你也添加了用来在用户和控件交互的时候更新用户界面的代码。现在项目仍然相当简单,只有一个场景,但是在接下来的课程中,你将继续添加功能,并增加它的复杂性。

注意
要想看本课完整的例子项目,下载这个文件并在Xcode中查看。

下载文件

(本节完毕。明天会添加图片拾取器。)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容