第2章 创建用户登录界面
让我们从上一章的LeanCloud云端回到Xcode 8,因为在利用模板生成项目的时候, Device设置成了iPhone,所以当打开Main.storyboard故事板文件的时候,只能看到一个iPhone屏幕大小的视图,我们会一直沿用这个大小的屏幕视图。
2.1 从故事板中创建视图
对于iOS应用程序开发来说,我们总是要从用户界面开始构建项目,这是因为移动端的应用程序都是基于用户交互的,大部分的代码都是在用户单击按钮或者是划动屏幕之后才被执行的。
步骤1 从通用工具区域的对象库(快捷键“control+option+command+3”)中找到View Controller,将该对象拖曳到故事板中View Controller视图的右侧,再拖曳另一个View Controller到之前View Controller的右侧,如图2-1所示。
图2-1 在故事板中新添加2个View Controller
步骤2 在项目导航中删除Single View Application模板为我们自动创建的ViewCon-troller.swift文件,在弹出的对话框中单击Remove Reference按钮。然后在Instagram组(黄色图标)上右击鼠标,在弹出的快捷菜单中选择New File,在新文件模板选择面板中选择iOS→Source→Cocoa Touch Class,单击Next按钮,如图2-2所示。
图2-2 选择新添加文件的类型
提示
删除对话框中的Remove Reference选项代表只删除该文件在项目中的链接,而不真正删除项目中的文件。Move to Trash则真正删除项目中的文件。
步骤3 在文件选项面板中,将Class设置为SignInVC, Subclass of设置为UIView-Controller, Language设置为Swift,单击Next按钮。使用默认的存储位置,单击Create按钮。
步骤4 因为在故事板中一共创建了三个控制器对象,所以在代码中也要相应地创建三个视图控制器类。重复上一步的操作,再创建SignUpVC和ResetPasswordVC两个控制器类。注意,Subclass of都确保设置为UIViewController,如图2-3所示。
图2-3 创建SignUpVC控制器类
步骤5 回到Main.storyboard,在编辑区域中选择左边第一个视图控制器,然后打开通用工具区域的Identity Inspector(快捷键“option+command+3”),将Custom Class部分中的Class设置为SignInVC。使用同样的方法,将第二个视图控制器的Class设置为SignUpVC,将第三个视图控制器的Class设置为ResetPasswordVC,如图2-4所示。
图2-4 在故事板中关联三个控制器类
通过步骤5的操作,我们可以分别在新创建的三个类中控制故事板中的三个控制器视图了。
2.2 搭建用户的登录界面
故事板中最左侧的视图现在与SignInVC类关联,接下来需要在这个视图上创建用户的登录界面,该界面包括两个Text Field和三个Button。
步骤1 在对象库中找到Text Field(利用对象库底部的过滤框,可以进行快速筛选),将其拖曳到最左侧的视图之中,大小和位置如图2-5所示。复制第二个Text Field,并将它放置在第一个的下方。
图2-5 在SignInVC视图中创建2个Text Field
技巧
除了使用Command+C和Command+V进行复制粘贴以外,我们还可以按住option键,然后从第一个Text Field拖曳鼠标到下面的位置。在拖曳的时候,鼠标会变成绿色带加号的圆圈,当复制完成时一定要先松开鼠标再抬起option键,否则只是进行简单的移动操作。
步骤2 选中上边的Text Field控件,在Attributes Inspector(快捷键“Command +option + 4”)中将Placeholder设置为用户名,Clear Button设置为Is always visible。使用同样的方法,将下面Text Field的Placeholder设置为密码,同样将Clear Button设置为Is always visible。同时,一定要勾选Secure Text Entry,如图2-6所示。
图2-6 设置密码Text Field的属性
Clear Button代表清除按钮,它会出现在Text Field的最右边。当Text Field中包含文字内容的时候,可以借助Clear Button清除文本信息。Clear Button在什么时候出现,这取决于所设置的属性值,属性值有以下几种情况:
❑never:清除按钮永不出现,是Clear Button的默认属性值。
❑whileEditing:只有在Text Field处于编辑状态的时候才会出现。
❑unlessEditing:只有在Text Field处于非编辑状态的时候才会出现。
❑always:Clear Button不管什么时候都会出现在Text Field的右边。
步骤3 从对象库中拖曳一个Button到Text Field的下面,调整好按钮的位置和宽度,确保处于选中状态,在Attributes Inspector中将Title设置为登录。为了美观,可以在登录两个字中间添加空格。再复制一个登录按钮,将其放在之前按钮右边对应的位置,并将Title改为注册。再添加第三个按钮,将它放置在Text Field和刚才两个Button之间的位置。在Attributes Inspector中修改字号为13,在Size Inspector中将width和height分别设置为100和14,在Alignment中将Horizontal设置为左对齐,将Title设置为忘记密码?,如图2-7所示。
图2-7 设置“忘记密码?”按钮的属性
步骤4 选中登录按钮,在Attributes Inspector中设置Text Color为White Color, Back-ground为亮蓝色。选中注册按钮,同样设置Text Color为White Color,但Background为亮橘色,如图2-8所示。
图2-8 设置按钮的背景颜色
步骤5 按住control键,然后在注册按钮上拖曳鼠标到右侧的第二个视图控制器上,在弹出的快捷菜单中选择Present Modally,如图2-9所示。
图2-9 为注册按钮与第二个视图创建Segue过渡
构建并运行项目,当我们单击注册按钮的时候,马上会跳转到注册视图,只不过现在的注册视图上,我们还没有搭建任何的用户界面控件。而神奇的是,在这一过程中我们并没有编写任何的代码。
2.3 为SignInVC类和视图创建Outlet和Action关联
2.3.1 什么是Outlet和Action
Outlet和Action是将视图控制器类(存储在swift文件中的类)和界面视图(故事板中的控制器视图)关联起来,并进行交互的两种方式。这两种方式比较相似,但它们最终实现的目的不同。
Outlet 代码类与故事板中视图之间的对话要利用Outlet关联。任何的UI元素(UILabel、UIButton、UIImage、UIView等)都可以通过Outlet方式关联到视图控制器。当我们在代码类中使用@IBOutlet关键字实现Outlet关联以后,那么:
❑可以通过编写代码的方式更新UILabel等控件的文本或设置UIView的背景颜色。
❑可以获取到用户界面控件的状态和消息,比如UIStepper当前的值,NSAttributed-String的字号等。
Action 视图传递消息到控制器代码类则需要使用Action。Action在视图控制器中是一个方法,这与@IBOutlet关键字不同,它使用的是@IBAction关键字。只要有指定的事件发生,Action就会从视图传递一条消息到视图控制器代码类。Action(或者说Action method)就会在接到消息以后执行相关的代码。
注意
Action只能被设置在UIControl的子类上,这就意味着不能在UILabel或UIView上设置Action。
2.3.2 为SignInVC创建Outlet
步骤1 在项目导航中打开Main.storyboard故事板文件,并选中故事板中最左侧(负责用户登录)的视图。在Xcode的右上角单击助手编辑器模式(有两个圆圈的Icon),如图2-10所示。
图2-10 将Xcode切换到助手编辑器模式
技巧
在默认情况下,打开助手编辑器模式后,出现在编辑区域的两个窗口是左右排列的,如果你使用Macbook进行开发的话,屏幕会显得很拥挤,而且显示效果并不理想。此时,我们可以长按助手编辑器按钮,在弹出的快捷菜单中选择Assistant Editor on Bottom,这样就成为了上下排列的两个窗口了,如图2-11所示。
图2-11 将助手编辑器设置为上下排列
如果在编辑区域的主窗口中选择了SignInVC的视图,那么在下面的第二窗口中则会自动打开SignInVC.swift文件。如果打开的不是该文件的话,则需要通过第二窗口顶部的路径指示器手动将其打开。单击Automatic→Instagram→Instagram→SignInVC.swift即可,如图2-12所示。
图2-12 让位于下面的第二窗口打开指定文件
步骤2 按住Control键,在上边的Text Field控件上拖曳鼠标到下面窗口的SignInVC类中。在弹出的设置面板中,确定Connection设置为Outlet,再将Name设置为usernameTxt,单击connect按钮,如图2-13所示。
图2-13 在故事板和SignInVC类之间创建Outlet关联
步骤3 对下面的Text Field进行同样的操作,将Name设置为passwordTxt,如图2-14所示。
图2-14 设置passwordTxt的Outlet关联
步骤4 接下来再为三个按钮创建Outlet关联,Name分别设置为:signInBtn、signUp-Btn、forgotBtn,代码如下:
class SignInVC: UIViewController { //text fields @IBOutlet weak var usernameTxt: UITextField! @IBOutlet weak var passwordTxt: UITextField! // buttons @IBOutlet weak var signInBtn: UIButton! @IBOutlet weak var signUpBtn: UIButton! @IBOutlet weak var forgotBtn: UIButton! ……
这里我们一共创建了五个Outlet关联,两个Text Field和三个Button。当程序运行时,就可以在SignInVC类中通过代码修改这五个用户界面控件的属性。实际上,我们可以把Outlet属性理解为C语言中的指针,在程序运行时它会指向由故事板创建的特定UI对象,可以访问并控制该对象。
2.3.3 为SignInVC创建Action
只有Outlet还不行,当用户在屏幕上与UI对象交互的时候,还需要让这些UI对象给相应的代码类发送消息,这就需要我们创建Action关联。
步骤1 按住control键,在登录按钮上拖曳鼠标到下面窗口的SignInVC类中,因为创建的是方法,所以要将位置放在下面的方法部分中。在弹出的设置面板中,将Connection设置为Action(非常非常的重要!),再将Name设置为signInBtn_clicked, Type设置为UIButton,确 定Event为Touch Up Inside, Arguments为Sender后,单击connect按钮,如图2-15所示。
图2-15 为SignInVC添加Action方法
当我们将Connection设置为Action后,面板中的选项会立即发生变化。Name是UI对象发送的消息名称,同时也是类中的方法名称。Type是用户与哪个UI对象发生的交互,这里是UIButton, Event代表按钮的哪个事件被触发后会发送这个消息,Touch Up Inside是用户手指在按钮的上面抬起的时候。这里有两个关键点:一是手指在按钮的范围内,一是抬起时,它是非常标准和普通的按钮动作。
说到Event事件,与Button相关的事件还有很多,可以通过Connection Inspector(快捷键“option+command+6”)查看UI对象的事件都有哪些,如图2-16所示。
图2-16 通过Connection Inspector查看UI元素的关联信息
选中登录按钮,在Connection Inspector中可以查看登录按钮的Touch Up Inside事件被触发后,会向SignInVC类发送signInBtn_clicked消息,也就是执行SignInVC类的signInBtn_clicked(_:)方法。
步骤2 修改signInBtn_clicked(_:)方法,具体如下所示:
// 单击登录按钮 @IBAction func signInBtn_click(_ sender: UIButton) { print("登录按钮被单击") }
signInBtn_clicked(_:)方法带有一个参数sender,它指向的是触发该方法的按钮对象。如果有多个UI对象触发该方法的话,我们可以通过该参数判断用户到底是与哪个UI对象进行交互。
Print()函数负责将字符串输出到调试控制台中,方便进行调试。
构建并运行项目,单击屏幕上的登录按钮会在调试控制台中看到print()函数所打印的文字信息。单击注册按钮,则会跳转到SignUpVC类所定义的视图中,只不过现在这个视图里面还没有任何的东西,如图2-17所示。
图2-17 测试Action方法
2.4 调整模拟设备
Xcode 8默认模拟器使用的是iPhone SE设备,它是4英寸的屏幕。而我们在故事板中搭建用户界面的时候,默认使用的是iPhone 6s 4.7英寸的屏幕,如图2-18所示。
图2-18 通过Size Classes特性调整屏幕尺寸
如果此时在模拟器中运行项目的话,会出现UI对象超出屏幕范围的情况。在后面的课程中我们会利用代码和自动布局(Auto Layout)来解决不同屏幕尺寸的UI布局问题。但是目前,只需将模拟设备修改为iPhone 6或者6s即可,如图2-19所示。
图2-19 选择模拟的iOS设备
本章小结
开发iOS应用程序项目一般要从搭建用户界面开始,因为大部分移动端应用都是基于交互的,这也就意味着只有用户在与某个UI控件交互的时候,才会去执行特定的方法,从而执行某些代码。
Outlet和Action是代码类与用户界面对象之间进行交互的方式。通过Outlet可以在代码类中控制和访问用户界面对象,而用户在与UI控件交互以后就会发送特定消息,从而执行代码类中的方法。