连接UI到代码

本章,你将连接FoodTracker应用程序的UI到代码并定义一些可执行的动作。当你完成时,你的应用程序将是这个样子:

 

学习目标
在课程结束时,你将能够:
1.解释一个storyboard中的场景和view controller之间的关系
2.在storyboard中UI元素和源代码创建出口和连接动作
3.从文本字段处理用户输入并在UI中显示结果
4.使用一个类遵循一个协议
5.理解委托设计模式
6.在设计应用程序体系结构时,按照目标 - 动作模式

连接UI到源代码

在storyboard的元素链接到源代码。重要的是要了解storyboard和你写的代码之间的关系。在storyboard中,一个场景代表的一个内容屏,通常一个视图控制器。视图控制器实现您的应用程序的行为。视图控制器管理单个内容视图和

它的子子视图的层次。视图控制器在应用程序的数据模型之间协调信息流,它封装应用程序的数据,并且显示数据,管理其内容视图的生命周期,该设备被旋转时,处理方向改变,定义应用程序的导航,并响应用户输入的行为。在所有的

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元素出口

出口(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

 

posted @ 2015-06-30 00:51  jy02432443  阅读(2658)  评论(0编辑  收藏  举报