第四章练习Race Car - 编写一个跑车App吧

在这个练习中,你将创建race car类,App会提供一辆赛车,点击Honk(按汽车喇叭),就会展示这赛车的详细信息。App的用户界面请见图4-1。

Exercise: Race Car | Page 105

界面上有六个Label和一个Button控件,App可以显示赛车的属性,用户可以点击Honk,点击Honk时,不会响起汽车喇叭声,而是会在开发者日志(developer log)中写下一段信息。

你已经知道了App有哪些功能,那么打开Xcode吧,点击顶部菜单栏的File -> New -> Project(见图4-2)。

Page 106 | Chapter 4 : Diving Deeper

从模板中选择Single View Application(见图4-3)。

点击Next,在Product Name一栏输入RaceCar(见图4-4)

Exercise: Race Car | Page 107

Organization Name和Organization Identifier已经自动填写好了,如果没有填写好,输入你的姓名中间不要有空格。最后,Language选择Swift,Devices选择iPhone,点击Next。

接下来从左侧选择你要存放的文件夹,点击Create,保存工程(见图4-5)。

Page 108 | Chapter 4 : Diving Deeper

出现了工程的详细信息界面(见图4-6)。Project Navigator在左边,Standard Editor在中间,Inspector在右边。

Exercise: Race Car | Page 109

点击Project Navigator中的Main.storyboard文件,出现一个空白界面(见图4-7)。

我们这次开发的App仅限于在iPhone上使用,点击Inspector的上方第一个按钮,看起来像是一张纸折了一个角。到中间部分,不勾选Use Auto Layout选项。这时会出现一个对话框,选择iPhone。然后不勾选Disable Size Classes。这时,Storyboard中的界面形状会改变(见图4-8)。我们将会在第七章详细介绍Auto Layout的知识。

Page 110 | Chapter 4 : Diving Deeper

确保Inspector在屏幕的右方。如果没有出现在屏幕右方,点击Inspector View Button(见图4-9),就是右上角右边有一条条纹的按钮,这样就可以显示Inspector了。

Inspector下方有个小的工具栏按钮,Object Library图标是从左往右第三个(圆圈中有个小方块)。

打开Object Library后,在搜索输入Label(见图4-10),将三个Label控件拖入到界面中,垂直对齐放在界面的右边(见图4-11)。

Exercise: Race Car | Page 111

三个Label对齐后,按住鼠标左键然后拖拽,覆盖三个Label,这样三个Label就被选中了(见图4-12),接着,到顶部菜单栏中选择Edit -> Copy或者按Command+C(见图4-13)。

Page 112 | Chapter 4 : Diving Deeper

接着到顶部菜单栏选择Edit -> Paste或者按Command+V(见图4-14)。

Exercise: Race Car | Page 113

这样又添加了三个Label控件,把这三个新的Label选中,然后拖到界面的右边,让Label对齐(见图4-15)。

Page 114 | Chapter 4 : Diving Deeper

有时候复制粘贴控件比起从Object Library中拖拽控件会更方便。最后,把Object Library搜索框中的label文字删掉,输入button(见图4-16)。

从Object Library中拖一个Button控件,放到两组Label中间(见图4-17)。

Exercise: Race Car | Page 115

双击界面左上角的Label,替换文字为Brand,双击左边中间的Label,文字更换为Color,最后双击左边最下方的Label,文字更换为Top Speed(见图4-18)。如有需要,重新调整Label的对齐。

Page 116 | Chapter 4 : Diving Deeper

右边Label中展示左边Label的具体值。见表格4-1。

表格4-1 Race Car
品牌 Ferrari
颜色 红色
最高时速 200 mph

双击Storyboard中的右侧的Label,然后问text修改为????(见图4-19)。然后将右侧的Label 宽度拖拽至60pts。

Exercise: Race Car | Page 117

最后,双击Button然后输入Honk,接着拖拽Button右上角的小方块,把宽度调整到60pts(见图4-20)。

Page 118 | Chapter 4 : Diving Deeper

现在,界面已经布局完成了,接下来需要把界面和controller连接起来。在这里,controller就是ViewController.swift文件。点击屏幕右上角的Assistant Editor按钮,打开Assistant Editor界面(见图4-21)。

为了能够有更多空间,我们把Inspector隐藏起来(点击屏幕右上角的Inspector View按钮)。

Assistant Editor会自动打开ViewController.swift文件,可以同上Assistant Editor顶部文件路径确认,就在Automatic这个词后面。

不是所有的控件都要连接到ViewController.swift文件中,如果这个控件是静态的或者无需变化,就没有必要连接。左侧的三个Label一直不变,那么就不需要连接。

选择右侧的Label,按住Control按钮,拖到下面这行代码的下方:

class ViewController: UIViewController {

当出现一条蓝色横线时,松开鼠标(见图4-22);弹出连接对话框窗口(见图4-23)。

Exercise: Race Car | Page 119

connection选择Outlet,Name输入brandLabel,点击Connect。

之后会自动生成一行代码:

@IBOutlet var brandLabel : UILabel!

第一个关键词@IBOutlet是来表示这是一个oulet连接类型,var表示这是一个变量,brandLabel就是这个变量的名字,冒号后面跟着变量的类型UILabel。brandLabel变量就代表了右侧最上面的Label。

Page 120 | Chapter 4 : Diving Deeper

然后选择界面上右侧中间的Label,同时按住Control键,拖到下面这行代码的下方:

class ViewController: UIViewController {

注意不要在brandLabel的代码上松开鼠标,如果你把鼠标错误的放到了其他的Label代码上方,和出现一个蓝色盒子。一定要在出现一条蓝色横线时,松开鼠标(见图4-24);弹出连接对话框窗口(见图4-25)。

connection选择Outlet,Name输入colorLabel,点击Connect。

Exercise: Race Car | Page 121

之后会自动生成一行代码。

然后选择界面上右侧底部的Label,同时按住Control键,拖到下面这行代码的下方:

class ViewController: UIViewController {

当出现一条蓝色横线时,松开鼠标(见图4-26);弹出连接对话框窗口(见图4-27)。

connection选择Outlet,Name输入topSpeedLabel,注意使用驼峰命名法,点击Connect。

会自动生成一行代码。

Page 122 | Chapter 4 : Diving Deeper

最后把Button连接到controller中。当用户点击Button时,Button会在controller中触发一个事件,这种连接模式叫做action。

选中界面中间的Button,同时按住Control键,拖到下面这行代码的下方:

class ViewController: UIViewController {

当出现一条蓝色横线时,松开鼠标(见图4-28);弹出连接对话框窗口(见图4-29)。

Exercise: Race Car | Page 123

因为这次连接的控件是Button,所以connection选择Action,点击Connection右侧的下拉菜单,选择Action,然后Name输入honkTapped,点击Connect。

会自动生成一行代码,Action连接创建的是方法,Outlet连接创建的是变量。每次用户点击Button时,honkTapped方法就会被调用。看一下Xcode生成的这段代码:

@IBAction func honkTapped(sender : AnyObject) {

}

第一个关键词@IBAction是来表示这是一个action连接类型,func表示这是一个方法,honkTapped就是这个方法的名字,括号内是方法的参数,括号里是参数的名字和类型,冒号后面就是这个参数的类型AnyObject。AnyObject起一个placeholder的作用,可用表示任何类型的对象。sender参数指向触发action的控件,sender参数根据控件的不同可以有很多不同的类型,像是Button,Slider,或者Segmented Control。

现在界面上所有需要连接的控件都已经连接到controller中了,是时候来创建你的race car了。然而,苹果并没有提供一个race car的类,没关系,你可以自己创建一个race car类。

选择File -> New -> File(见图4-30)

Page 124 | Chapter 4 : Diving Deeper

接着选择Cocoa Touch Class(见图4-31)。

Exercise: Race Car | Page 125

在Class一栏中输入RaceCar(见图4-32),Subclass设置为NSObject,Language选择Swift,点击Next。

Xcode接下来会让你选择存储地点,RaceCar工程已经自动选择了,如果没有,选择RaceCar文件夹,点击Create(见图4-33)。

Page 126 | Chapter 4 : Diving Deeper

这时在Project Navigator中有了一个新文件RaceCar.swift(见图4-34)。

Exercise: Race Car | Page 127

你的这个RaceCar类应该有三个属性和一个方法:brand,color,top speed以及honk方法,当RaceCar honk时,会在调试窗口打印出一行信息。开发者一般在调试窗口调试变量和事件。用户是无法看到developer log,这也是一个调试解决bug的好工具。

给你的RaceCar写下第一个属性:

class RaceCar: NSObject {
    var brand: String = "Ferrari"
}

增加属性看起来像是在创建变量,不过属性是可以让其他对象获取的。var用了创建属性,var后面跟着属性名称,接着冒号后面跟着属性的类型,等号后面是属性的值,字符串用双引号括起来。

接着增加第二个属性:

class RaceCar: NSObject{
    var brand: String = "Ferrari"
    var color: String = "Red"
}

color属性的格式和语法与brand属性相同。属性名字是color,默认值是Red,类型是String,用户双引号将字符串的内容括起来。

最后,增加第三个属性:

class RaceCar: NSObject {
    var brand: String = "Ferrari"
    var color: String = "Red"
    var topSpeed: Int = 200
}

topSpeed的属性多少有些不同了,类型是Int,因为最高时速是一个整型数字,所以默认值设置为200,属性是Int。

现在RaceCar类的属性已经都写完了,从RaceCar类中创建的车都会有brand,color和top speed这三个属性,默认值是"Ferrari","Red"和200。

RaceCar类还需要有一个honk行为,也就是honk方法,那么,我们把honk方法添加到RaceCar类中:

Page 128 | Chapter 4 : Diving Deeper

class RaceCar: NSObject {
    var brand: String = "Ferrari"
    var color: String = "Red"
    var topSpeed: Int = 200

    func honk() {
        print("Honk! Honk!")
    }
}

func关键词用来声明方法,honk是这个方法的名字,括号里是空的表示这个方法没有参数值。

在方法里面,用两个左右大括号包起来,只有一行代码,就是print这行代码,将"Honk! Honk!"打印到Debugger窗口中。

Debug Console或者Debugger(调试窗口),在写代码时候一般是隐藏的,当程序运行时,会出现(见图4-35)。打开Debugger的方法:屏幕右上角中间按钮,方块下方有一条横线的按钮,点击打开,再次点击隐藏。

现在RaceCar类已经写完了,那么,现在用RaceCar这个类来创建一辆跑车吧。快捷键Command+S保存刚刚的操作。

Exercise: Race Car | Page 129

点击打开Project Navigator里的ViewController.swift文件,点击右上角Standard Editor按钮来隐藏收起Assistant Editor。

把鼠标光标放到honkTapped方法中,然后添加下面的代码:

@IBAction func honkTapped(sender: AnyObject) {
//Create Car
//Display Car 
//Honk Car
}

把鼠标光标放到//Create Car这行代码后面然后敲击回车,输入下列代码:

var myCar = RaceCar()

var用了创建变量,myCar是变量名,等号表示把等号右边的值复制给等号左边的变量。最后,用RaceCar()创建一个新的RaceCar。

RaceCar()调用RaceCar类的初始化方法,把默认值返回给这个新的RaceCar(也就是myCar)。这初始化方法是Xcode自动生成的。从一个类中创建对象,写下这个类的名字,后面跟上一对括号。在这里的这个例子中,没有参数,所以括号内是空的。

现在这个新的RaceCar赋给了myCar变量。把鼠标光标放到//Display Car后面然后敲击回车,写下下方代码:

brandLabel.text = myCar.brand

这行代码的作用是把myCar这个变量中的brand赋值给界面上brandLabel这个控件中text属性。在这里,brandLabel上显示的文字是"Ferrari",点这个符号可以获取Label的属性和方法,例如此处跟上了text这个属性。

myCar这个变量表示刚刚创建的新的RaceCar,后面的点符号可以获取RaceCar的属性和方法,例如此处获取了brand这个属性,这个属性返回一个string类型的值,和brandLabel的text属性类型对应一致。

在//Display后面敲击回车,输入下方代码:

colorLabel.text = myCar.color
topSpeedLabel.text = "\(myCar.topSpeed)"

你可能会注意到,colorLabel这行代码和上面的brandLabel代码非常相似。这行代码获取了RaceCar的color属性然后赋值给了colorLabel这个控件,默认值是"Red"。

Page 130 | Chapter 4 : Diving Deeper

topSpeed这行代码和前面两行稍微有些不同,topSpeedLabel这个控件应该显示的RaceCar的topSpeed这个属性,Label.text需要的是string类型的值,然后RaceCar的topSpeed这个属性的值是Int类型,类型不一致,需要转换,使用()即可转换。

鼠标光标放到//Honk后面,然后敲击回车,输入下方这行代码:

myCar.honk()

这行代码会触发RaceCar的honk方法(点符号可以获取对象的属性和方法),然后就会在Debugger中看到一行消息。括号里空的表示没有参数。

现在可以运行App看看效果了。点击左上角的Play按钮(或者快捷键Command+R),Xcode会启动模拟器(见图4-36)。

Exercise: Race Car | Page 131

App启动后,点击Honk这个按钮(见图4-37)。

RaceCar的属性都显示在对应的Label中了,点击Honk按钮后,会调用honk()方法,然后在Debugger中打印一段信息:“Honk! Honk!”

Page 132 | Chapter 4 : Diving Deeper

如果App没有按照你想要的结果运行,或者程序有了错误或警告,不要太担心,学习的最佳方式就是试错,熟能生巧,到我们的网站上下载示例代码,对比一下代码,多试几次,直到搞定这个程序为止。

Exercise: Race Car | Page 133