你的第一个iOS应用(四) 配置视图

配置视图

提供了一些对象的库,可以让你添加到故事板文件中. 有些是用户界面元素属于视图的,比如按钮和文本框.还有一些其他更高级的对象,比如视图控制器和手势识别器.

这个Hello World View Controller场景已经包含了一个视图. 现在你需要添加一个按钮,一个标签,和一个文本框. 然后, 您在这些元素和视图控制器类之间建立连接,这样这些元素就能提供给你需要的行为.

添加用户界面元素

你可以通过从对象库拖拽这些界面元素到画布的视图上面,来添加用户界面(UI)元素. 这些UI元素拖拽到视图后, 你就可以对这些元素进行适当的移动及调整大小.

bullet
去添加一些UI元素到视图中,然后将他们摆放到适当的位置 . . .
  1. 如果有必要,在工程导航器中(project navigator)选择MainStoryboard.storyboard , 好让画布上显示出来Hello World View Controller的场景.(如果已经打开则无需重复做此步)

  2. 如果有必要,打开对象库.

    对象库位于实用工具区域的底部. 如果你没有看到对象库, 你可以在库选择栏(library selector bar)上点击从左数的第三个按钮:

    image: ../Art/object_library.png
  3. 在对象库里,从Objects的弹出菜单中选择Controls.

    Xcode就会在弹出菜单的下方显示控件列表. 这个列表显示了每一个控件的名字,外观,和描述其功能的简短描述.

  4. 一次只能拖拽一个控件, 分别拖拽一个文本框(Text Field),一个圆角矩形按钮(Rounded Rect Button),以及一个标签(Label) 到视图上面.

    image: ../Art/dragging_text_field.jpg
  5. 然后拖拽视图中的文本框到视图左上角附近

    在你移动(拖拽)文本框的时候 (或者其他任何一个UI元素), 一个被成为对齐参考线 的蓝色虚线—显示出来以帮助你可以对齐控件到视图的中心和各个边. 在你看到视图的左边和上面的对齐参考线的时候就可以停止拖拽文本框了, 如下所示:

    image: ../Art/moving_text_field.jpg

  6. 准备调整视图中文本框的大小.

    你可以通过拖拽它的 尺寸调节柄 来调整一个UI元素的大小. 通常情况下,你通过在画布上或者大概视图中选择元素,就可以看到元素的 尺寸调节柄. 在这个情况下, 因为你刚才停止拖拽文本框,所以这个文本框应该已经被选中了. 如果你的文本框看起来和下图类似,你就可以准备调整文本框的大小了; 如果和下图不一样, 就在画布或者大概视图中选中文本框.

    image: ../Art/resize_handles.jpg
  7. 拖拽这个文本框右边的 尺寸调节柄 直到视图右边显示出对齐参考线为止.

    当你操作到类似下图状态的时候,就可以停止调整尺寸了:

    image: ../Art/extending_text_field.jpg
  8. 选中文本框(如果未选择),打开属性察看器.

  9. 在文本框的属性察看器顶部附近的Placeholder字段中,输入短语 Your Name.

    它的名字将作为建议(暗示), PlaceHolder字段提供了一段浅灰色的文本,用于在应用运行的时候,可以让用户知道他们在文本框中可以输入信息的类型, 这个placeholder文本一旦用户在文本框的内部点击就会消失(实际上是如果文本框内容为空,则显示. 不为空,则不显示).

  10. 还是在文本框的属性察看器里,点击居中对齐按钮 让文本框的文本居中对齐.

    在你输入完placeholder文本并改变了对齐设置后,你文本框的属性察看器应该会看起来像这样:

    image: ../Art/text_field_attributes.png
  11. 在视图中,拖拽这个标签以便让它放置在文本框的下面并且它的左边要和文本框的左边对齐.

  12. 拖拽这个标签右边的 尺寸调节柄 直到标签和文本框的宽度一致为止.

    一个标签的尺寸调节柄会比文本框更多. 这也就意味着你可以同时修改标签的宽与高 (你只能修改文本框的宽). 你不需要去改变标签的高, 因此只需要拖拽标签正右方向的尺寸调节柄即可,不要去调节其他的尺寸调节柄.

    image: ../Art/resize_label.png
  13. 在标签的属性察看器中,点击居中对齐按钮(来让标签中所显示的文本居中).

  14. 拖拽按钮 以便让按钮放置在视图的底部附近并且水平居中.

  15. 在画布上,双击按钮并输入文本Hello.

    当你在视图中双击按钮的时候(在输入文本之前),你应该会看到如下图所示的这样:

    image: ../Art/button_double_clicked.jpg

在你添加完文本框,标签,及按钮的UI元素并按照上述建议改变布局后,你的工程应该会看起来像下图这样:

image: ../Art/after_layout.jpg

你可以给文本框改变几个地方它的行为可以表现的和用户期待的那样. 首先,因为用户将会输入他们的名字,因此你要确保iOS建议他们所输入的每一个单词都是大写开头的. 其次,你要确保键盘与文本框为输入名字所作的配置相关联(例如 不能是数字),并且要在键盘上显示一个Done按钮.

这个就是更改这些的原因: 因为在设计的时候,你是知道文本框将要包含哪种类型的信息的,因此你可以配置它以便让它在运行时的外观与行为可以适合用户的操作.你在属性察看器中改变这些配置.

bullet
去配置文本框 . . .
  1. 选择视图中的文本框.

  2. 在文本框的属性察看器中,进行以下设置:

    • 弹出菜单中,选择Words.

    • 确保Keyboard弹出菜单设置为Default.

    • 在Return Key弹出菜单中,选择Done.

    在你设置完这些选择后,文本框的属性察看器应该看起来像下图这样:

    image: ../Art/text_field_entry_attributes.png

运行你的应用来确定你所添加UI元素是否和你期待的一样. 如果点击Hello按钮,它应该会变成高亮,并且如果在文本框内部点击,则键盘应该会显示出来. 目前, 按钮不做任何事,标签为空,以及没有任何方法可以在键盘显示后关闭它. 要添加这个功能,你需要去在UI元素与视图控制器之间建立连接. 这个连接将会在下一节描述.

注意: 因为你是在模拟器中运行应用,而不是在设备上运行,所以你激活控件的方式是点击而不是触控.

为按钮创建一个动作(Action)

当用户激活一个UI元素的时候,这个元素会发送一个动作(action)消息到一个知道如何处理相应动作的对象的函数中(例如 "添加这个联系人到用户联系人列表").这个交互是target-action机制,是另一个Cocoa Touch的设计模式.

在这个教程中, 当你触控按钮的时候, 你希望它发送一个 "改变问候语" 的消息(这是action) 到视图控制器中(这是 target). 这个视图控制器将会通过改变它所管理的字符串(这里表示 模型对象)来响应这个消息.  然后,视图控制器用这个模型对象的值来更新标签所显示的文本来反映出这个改变.

你可以通过Control+拖拽的方式,将画布的元素拖拽到适当的源文件中(通常,是一个视图控制器的源文件),以此来为一个UI元素添加一个动作和设置相应的动作函数.故事板保存着你以这种方式创建的连接. 以后,当应用加载故事板的时候,会重新建立这个连接.

bullet
去为按钮添加一个动作 . . .
  1. 如果有必要, 在工程导航器中选择 MainStoryboard.storyboard 来显示出画布上的场景.

  2. 在Xcode的工具栏上, 点击实用工具按钮来隐藏实用工具区域, 然后点击助手编辑器( Assistant Editor ) 来显示辅助编辑器面板.

    这个助手编辑器按钮是编辑按钮位于中间的按钮, 它如右图所示: image: ../Art/assistant_editor_button.jpg.

  3. 确保这个助手显示了视图控制器的实现文件(在这里是 HelloWorldViewController.m).

    如果他显示的是HelloWorldViewController.h 那就从工程导航器中选择HelloWorldViewController.m .

  4. 在画布上,从Hello按钮按住Control并拖拽到HelloWorldViewController.m类的扩展(class extension)上.

    在一个实现文件中的类的扩展,是一个放置声明一个类私有的 属性(property)和方法(methods)的地方. (你将会再Write Objective-C Code学习到更多关于类的扩展的知识.)  Xcode的模版给视图控制器的实现文件种包括了一个类的扩展; 在这个HelloWorld工程中, 这个类的扩展看起来像下面这个:

    注意类扩展不是.h文件的,而是.m文件的, 如果你的.m文件和下面的图示不一样,则要手动添加代码,将下面的代码添加到如图示那样为止即可! 不要和.h的@interface类声明搞混.

         这个类扩展是新加入的,我记着以前版本的Xcode是好像是没有类扩展的..

    @interface HellowWorldViewController()    //这里后面和.h的interface不一样!!!
     
    @end

    要去进行Control+拖拽, 在你把按钮拖拽到助理编辑器面板的实现文件中的同时,还要按下并按住Control键. 在你进行Control+拖拽操作的时候,你会看起来像下图一样::

    image: ../Art/dragging_for_action.png

    当你松开Control键并停止拖拽的时候,Xcode显示一个弹出气泡窗口,可以让你去设置你的动作连接(action connection):

    image: ../Art/connection_popover.png

    注意: 如果你在停止Control+拖拽操作的时候, 没有在HelloWorldViewController.m的类的扩展区域内的话, 你也许会看到一些不同类型的气泡窗口或者什么都不显示. 如果发生这种事,就点击一下画布上场景的内部来关闭这个气泡窗口,并且再次尝试Control+拖拽的操作

  5. 在这个气泡窗口里,设置按钮的动作连接:

    • 在Connection弹出菜单中,选择Action.

    • 在Name字段里,输入 changeGreeting: (确保要包含冒号)

      在稍后的步骤中,你将会实现这个changeGreeting:  函数,以便可以让它将用户在文本框输入的文本显示到标签上.

    • 确保Type字段包含id.

      这个id数据类型可以表示任何Cocoa对象. 你在这里使用id类型是因为是什么它不知道发送这个消息的对象的类型是什么.

    • 确保Event弹出菜单包含Touch Up Inside.

      你指定这个Touch Up Inside事件是因为你想要当用户在按钮内部抬起手指时,发送这个消息.

    • 确保Arguments弹出菜单包含Sender.

    在你设置好动作连接之后,将会看到类似下图这样:

    image: ../Art/action_popover.png
  6. 在气泡窗口中 点击Connect.

    Xcode会添加一个新的changeGreeting:空实现的函数并且通过在这个函数的左侧被填充的环形来表示连接已经创建:

    image: ../Art/action_connection_made.png

当你Control+拖拽这个Hello按钮到HelloWorldViewController.m文件的类的扩展并且设置了产生的动作,那么你已经做了两件事了: 你通过Xcode在视图控制器的类中(在HelloWorldViewController.m中)添加了适当的代码,并且你在按钮与视图控制器之间创建了一个连接.Xcode会明确地做如下几件事:

  • 查看HelloWorldViewController.m,它在类的扩展中添加了如下动作函数的声明:

    - (IBAction)changeGreeting:(id)sender;				//这段代码在类的扩展生成

    并且在实现区域中添加了下列空实现的函数:

    - (IBAction)changeGreeting:(id)sender {				//这段代码会实现部分生成
    }

    注意: IBAction是一个特殊的关键字,用来告诉Xcode将一个函数视为target-action连接的action,IBAction 定义为 void 类型.

    在这个动作函数中sender参数,引用着发送这个动作消息的对象 (在这个教程中, sender就是按钮).

  • 它在按钮和视图控制器之间创建一个连接.

接下来,你要在视图控制器和剩余的两个UI元素进行连接(也就是 标签和文本框).

给文本框与标签创建出口变量(Outlets)

一个出口变量(outlet) 描述了两个对象间的连接. 当你想让一个对象(例如 视图控制器)去传递一个它获取到的对象(例如 文本框)的时候,你将这个被获取的对象(例如 文本框)指定为一个出口变量(outlet). 当应用程序运行时,Xcode将会重新建立你所创建的出口变量,允许在运行时对象间进行互相传递.

在这个教程中,你希望视图控制器获取用户在文本框中输入的文本,然后显示在标签上. 要确保视图控制器可以传递这些对象,你要在他们之间去创建出口变量(outlet).

这一步你要去添加文本框与标签的出口变量,它和你刚才添加按钮的动作的操作非常相似. 在你添加之前, 确保这个主故事板文件的画布是可视的并且在助理编辑器中HelloWorldViewController.m仍然被打开着.

bullet
去添加文本框的出口变量(outlet) . . .
  1. 在视图中 按住Control键,并拖拽文本框到实现文件的类的扩展中.

    当你正在Control+拖拽的时候,你应该会看到如下图这样:

    image: ../Art/dragging_for_outlet.png

    你只要按住Control并拖拽到到类扩展的内部即可. 在这篇教程中,这个出口变量声明是显示在Hello按钮函数声明的上面的.

  2. 当你松开Control键并停止拖拽时,气泡窗口就回弹出,来让你设置文本框的连接:

    • 确保Connection弹出菜单包含Outlet.

    • 在Name字段中, 输入"textField".

      你可以给这个出口变量(outlet)起一个你想要的名字, 但是你如果能把一个outlet的名字和表示这一条目关联起来的话,那么你的代码会更加容易理解(命名要有意义,才好理解. 不要随便写个a啊,b啊,之类的名字,这样以后代码很不好阅读)..

    • 确保Type字段包含 "UITextField",来确保Xcode只去连接 文本框的出口变量(outlet).

    • 确保Storage弹出菜单包含 Weak, 默认值就是它.

      Acquire Foundational Programming Skills中,你以后将会学习到更多关于stong和weak storage的知识

    After you make these settings, the popover should look like this 在你完成这些设置之后, 气泡窗口应该会是下图这样:

    image: ../Art/configure_text_field_outlet.png
  3. In the popover, click Connect.

通过添加文本框的一个出口变量(outlet)你已经完成了两件事, 如下:

  • Xcode在视图控制器类的实现文件(HelloWorldViewController.m)中,添加了适当的代码.

    实际上,它就是在类扩展里加入了如下代码:

    @property (weak, nonatomic) IBOutlet UITextField *textField;

    注意: IBOutlet是一个特殊的关键字用来告诉Xcode将它视为一个出口变量(outlet). 它实际上在编译的时候没有任何的影响.

    viewDidUnload函数中添加如下表达式:

    self setTextField:nil;

    这个viewDidUnload函数是你在Xcode所选择的模板为你提供的,而且这个函数是通过UIKit框架为你实现的. 一个视图控制器当它需要卸载掉它所包含的视图时,就会调用viewDidUnload函数, 因此在这个函数将视图的出口变量(outlet)设置为nil才是正确的.

  • Xcode从视图控制器到文本框创建了一个连接.

    通过在视图控制器和文本框之间创建连接, 用户输入的文本可以传递到视图控制器中. 当Xcode已经生成changeGreeting:函数声明的时候,表示连接已经创建了,这时候会再文本字段(Text Field)声明的左边会显示一个已经被填充的圆形.

注意:  早期的Xcode版本会在你使用Control+拖拽方法的时候,给你在实现块(implementation block)中给你的每一个声明的属性(property)添加一个@synthesize指令. 因为编译器会自动合成存取器函数(synthesizes accessor methods),因此这个指令已经没有必要了. 你可以很放心的删除它们了.

现在来添加一个标签的出口变量(outlet)并设置连接. 在视图控制器和标签之间建立连接, 可以让视图控制器用获取到的用户输入的文本来更新标签的内容. 这一步的过程和你之前添加文本框的出口变量(outlet)是一样的, 不过还要适当的更改下连接的设置. (确保助手编辑器仍然显示着HelloWorldViewController.m文件.)

bullet
去添加一个标签的出口变量(outlet) . . .
  1. 在视图的标签上,按住Control键并拖拽到助手编辑器的HelloWorldViewController.m文件中的类扩展位置.

  2. 在你松开Control键并停止拖动的时候会弹出气泡窗口,就可以设置标签的连接了:

    • 确保Connection弹出菜单包含Outlet.

    • 在Name字段中,输入"label".

    • 确保Type字段包含“UILabel”.

    • 确保Storage弹出菜单包含Weak.

  3. 在气泡窗口,点击Connect.

通过这个教程,你目前为止已经创建了总共三个连接到你的视图控制器中了:

  • 一个按钮的动作(action)连接

  • 一个文本框的出口变量(outlet)连接

  • 一个标签的出口变量(outlet)连接

你可以在连接察看器(Connections inspector)上检查一下这些连接.

bullet
去打开视图控制器的连接察看器( Connections inspector) . . .
  1. 点击标准编辑器(Standard editor)按钮去关闭助手编辑器并且切换到标准编辑视图.

    这个标准编辑器按钮在编辑器按钮的最左边, 它的图标是这个的: image: ../Art/standard_editor_button.jpg

  2. 点击实用工具视图按钮去打开实用工具区域.

  3. 在大纲视图中选择Hello World View Controller.

  4. 在实用工具区域显示连接察看器.

    这个连接察看器是查看选择栏(inspector selector bar)最右边的按钮, 它的图标是这个: image: ../Art/connections_inspector_button.jpg

在连接察看器中,Xcode显示所选对象的连接 (在这个情况下, 显示的是视图控制器的连接). In your workspace window在工作区窗口,你应该会看到类似于下图这样的:

image: ../Art/verify_connections.png

你会看到视图控制器和它的视图之间有一个连接,另外还可以看见你所创建的三个连接. Xcode会提供一个默认的 视图控制器与它视图间的连接; 你无法用任何方式访问它.

建立文本框的代理连接(Delegate Connection)

在你的应用中,你已经创建了超过一个连接了: 你需要去连接文本框到一个作为文本框代理的对象上面.在这个教程中,你实用视图控制器来作为文本框的代理

你需要指定一个文本框的代理. 这是因为当用户触控键盘上的Done键时,这个文本框会向代理发送一个消息 (回忆一下之前所讲述的吧, 一个代理就是一个对象,这个对象代表着另外一个对象的动作.  在这里就是视图控制器为代理,而另一个对象则是文本框). 在稍后的步骤中,你将会使用与这个消息所关联的函数来让键盘消失.

确保故事板文件已经在画布上打开了. 如果还没有打开,在工程导航器中选择MainStoryboard.storyboard.

bullet
去设置文本框的代理 . . .
  1. 在视图中的文本框上按住Control键并拖拽到场景停靠栏(scene dock)中的黄色球体图标上 (这个黄色球体图标代表一个视图控制器对象).

    当你松开Control键并停止拖拽时,会看到如下图所示的这样:

    image: ../Art/text_field_delegate.jpg
  2. 在显示出来的半透明的面板的 Outlets 部分选择delegate.

测试应用

点击Run并测试你的应用.

你应该会发现当你点击按钮时,它会高亮. 你还会发现如果点击文本框的时候,键盘会显示出来并可以输入文本. 但是你还是没有方法可以让键盘消失掉. 要做到这一点,你需要去实现相关的代理函数才行. 你会在下一章来做这件事. 现在,关掉模拟器.

概括

当你在画布的视图控制器与助手编辑器中实现文件(HelloWorldViewController.m)的类扩展之间创建了一个适当的连接的时候. 也会更新了实现文件来支持 出口变量(outlet)以及动作(action).

如果当创建一个连接的时候,没有使用Xcode的自动添加代码的功能(也就是 创建连接时 从画布上通过按住Control键并拖拽到源文件中这种方式). 你也可以去在类扩展或自身的头文件中 手动编写属性和函数声明,然后和你所做的文本框代理之间创建连接. 不过通常情况下你让Xcode帮你做这些工作比较好,这回减少错误(并且可以少打字).

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值