在本课中,你将继续使用FoodTracker应用的菜品场景的UI。你将重新排列现有的用户界面元素,并使用一个image pikcer(图片选择器)来添加图片到场景。当你完成后,你的应用看上去应该是这样的:
![image: ../Art/WWVC_sim_finalUI_2x.png](https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Art/WWVC_sim_finalUI_2x.png)
学习目标
在结束本课时,你将能够:
- 理解视图控制器的生命周期及其回调函数(例如,viewDidLoad,viewWillAppear,以及viewDidAppear)。
- 在视图控制器之间传递数据
- 关闭视图控制器
- 使用手势识别器(gesture recognizer)来生成事件
- 基于UIView/UIControl类层次结构来预测对象行为
- 使用asset catalog(资源目录)添加图片资源到项目
理解视图控制器生命周期
迄今为止,FoodTracker应用只有一个场景,它的用户界面通过单个视图控制器管理。当你构建更复杂的应用时,你将创建更多场景,并将为了视图能被移入或移出屏幕而管理它们的加载和卸载。
一个UIViewController类(及其子类)的对象有一系列的方法来管理它的视图层次结构。当视图控制器转换状态的时候,iOS会自动的在合适的时候调用这些方法。当你创建一个视图控制器的子类(例如你现在正在使用的ViewController类),它会继承定义在UIViewController类当中的方法,并且让你为每个方法添加你自己的自定义行为。理解系统何时会调用这些方法很重要,这样你才可以在合适的时候设置或撤下视图。
![image: ../Art/WWVC_vclife_2x.png](https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Art/WWVC_vclife_2x.png)
iOS会像下面这样调用UIViewController方法:
viewDidLoad()——当视图控制器的内容视图从storyboard被创建和加载的时候该方法会被调用。视图控制器的outlets在这个方法被调用的时候要保证有有效的值。使用这个方法来执行视图控制器要求的任何额外设置。
通常,iOS只能调用viewDidLoad()一次,是在它的内容视图第一次被创建的时候;但是当视图控制器首次实例化的时候,它的内容视图不一定被创建。相反,它是第一次系统或者任何代码访问控制器的view属性时候被懒创建(lazily created)的。viewWillAppear()—在视图控制器的内容视图被添加到应用的视图层次结构之前被调用。使用这个方法可以在内容视图显示在屏幕上之前触发任何需要进行的操作。尽管是这个名字,只是因为系统这样称呼这个方法,它并不保证内容视图是可见的。这个视图可能是透明的或者隐藏在其他视图后面。这个方法只是表明内容视图即将被添加到应用的视图层次结构中。
viewDidAppear()—在视图控制器内容视图已经添加到应用视图层次结构之后被调用。使用这个方法可以在内容视图刚刚被显示在屏幕上的时候触发任何需要进行的操作,例如获取数据或者显示一个动画。尽管是这个名字,只是因为系统这样称呼,它并不保证内容视图是可见的。这个视图可能是透明的或者隐藏在其他视图后面。这个方法只是简单的表明内容视图已经添加到了应用的视图层次结构中。
当然还存在着一组用来卸载视图的互补方法,就像上面示意图所示的那样。
你将在FoodTracker应用中使用其中的一些方法来加载和显示你的数据。事实上,如果你记得,你已经在ViewController中的viewDidLoad()方法里写了一些代码:
override func viewDidLoad() {
super.viewDidLoad()
// Handle the text field’s user input through delegate callbacks.
nameTextField.delegate = self
}
这种让视图控制器作为视图和数据模型之间的通信管道的应用设计模式被称为MVC(模型视图控制器Model-View-Controller)。在这种模式中,模型会跟踪应用的数据,视图显示用户界面并且构成应用的内容,控制器管理视图。通过响应用户的操作并用来自数据模型(data model)的内容来填充视图,而控制器是作为模型和视图之间通信的关口。MVC是所有iOS应用良好设计的核心,迄今为止,FoodTracker 应用已经沿着MVC原则构建了。
请记住MVC模式。现在是时候制作下一阶段的基础用户界面了,添加一个图片到菜品场景。
添加一个菜品照片
完善菜品场景的下一步是增加一种显示指定菜品图片的方式。为此,你将使用一个图片视图(UIImageView),一个用来显示图片的UI元素。
添加image view到场景
- 打开storyboard,Main.storyboard.
-
打开utility area中的Object library。(或者,选择View > Utilities > Show Object Library)。
image: ../Art/object_library_2x.png - 在Object library,在筛选字段输入image view快速找到Image View对象。
-
从Object library拖拽一个Image View对象到你的场景,让它在栈视图里面、在按钮下面。
image: ../Art/WWVC_imageview_place_2x.png -
选择image view后,打开utility area的Size inspector(尺寸检查器)
当你选择检查器选择器栏左起第五个按钮的时候,Size inspector会出现。它让你可以编辑storyboard中对象的尺寸和位置。
image: ../Art/WWVC_inspector_size_2x.png - 在Intrinsic Size(内在尺寸)字段,选择Placeholder。(这个字段在Size inspector底部,所以你需要向下滚动来看到)。
-
在Width和Height字段都键入320,按下回车键。
视图的内在内容尺寸(intrinsic content size)是指视图的尺寸是基于视图本身的内容。一个空的image view没有内在内容尺寸。只有你添加一个图片到视图,它的内在内容尺寸才会被设置为图片的尺寸。
提供占位符尺寸,可以给image一个临时的内在内容尺寸,这样就可以在设计用户界面的时候使用它了。这个值只是在Interface Builder中设计界面的时候有用;在运行的时候,布局引擎会使用视图真实的内在内容尺寸代替。
image: ../Art/WWVC_placeholdersize_2x.png -
在画布底部右侧,打开Pin菜单
image: ../Art/AL_pinmenu_2x.png -
选择Aspect Ratio(纵横比)旁边的复选框
这时的Pin菜单看上去是这样的:
image: ../Art/WWVC_imageview_aspectratio_2x.png - 在Pin菜单中,点击Add 1 Constraints按钮
- 在image view选中状态,打开Attribute inspector。
- 在Attribute inspector中,找到Interaction(交互)字段,并选择User Interaction Enabled复选框。
这个功能稍后你会需要,它让你的image view可以和用户交互。
你的场景现在是这样的:
显示默认照片
添加占位image来让用户知道他们可以和这个image view进行交互来选择一张图片。这张图片可以是从本课最后的可下载文件的Images/文件中的,也可以是你自己的图片。
![image: ../Art/defaultphoto_2x.png](https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Art/defaultphoto_2x.png)
添加一张图片到你的项目
- 在project navigator,选择Assets.xcassets来查看asset catalog(资源目录)。
这个asset catalog是一个为应用存放和组织图片资源的地方。 -
在左下角,点击加号(+)按钮,并从弹出菜单中选择(New Image Set)。
image: ../Art/WWVC_assetcatalog_2x.png - 双击image set名字,并重命名为defaultPhoto。
- 在你的电脑中,选择一张你想添加的图片。
-
拖拽并把图片放到image set中的2x插槽中。
image: ../Art/WWVC_defaultphoto_drag_2x.png
2x是本系列课程使用的iPhone 7模拟器的显示分辨率,因此图像在这种分辨率下会看起来最好。
进一步探索
更多关于图片分辨率的信息,查看iOS Human Interface Guidelines中的 Graphics > Image Size and Resolution
将默认的占位图添加到项目,设置image view来显示它。
在image view 中显示一张默认图片
- 打开storyboard。
- 在storyboard中选择image view。
- 选中image view,在utility area中打开Attributes inspector。
- 在Attributes inspector中,找到Labeled Image(图片标签) 字段,选择defaultPhoto。
检查点:运行应用。默认图片显示在了image view中。
![image: ../Art/WWVC_sim_finalUI_2x.png](https://developer.apple.com/library/content/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Art/WWVC_sim_finalUI_2x.png)
连接Image View到代码
现在,你需要实现在应用运行时改变这个image view中图片的功能。首先,你需要连接image view到ViewController.swift中的代码处。
连接image view到ViewController.swift代码。
-
点击Assistant 按钮。
image: ../Art/assistant_editor_toggle_2x.png -
如果需要更大的空间,点击如下图的按钮。
image: ../Art/navigator_utilities_toggle_on_2x.png
你也可以关闭大纲视图。
- 在storyboard中,选择image view。
-
按住Control键,从画布中的image view拖拽一条线到右侧编辑器的代码上,拖拽到如图所示的位置时,松手。
image: ../Art/WWVC_imageview_dragoutlet_2x.png -
在出现的对话框中,在Name字段,输入photoImageView。
剩余的选项保持不变。你的对话框看上去是这样的:
image: ../Art/WWVC_imageview_addoutlet_2x.png - 点击连接。
Xcode会添加必要的代码到ViewController.swift,用来存储image view的引用吗,并且配置storyboard来设置这个连接。
@IBOutlet weak var photoImageView: UIImageView!
现在你可以从代码访问image view来改变它的图片,但是你如何知道何时改变图片?你需要给用户一个用来指明他们想要改变图片的方式——例如,通过点击image view。然后,你将定义一个action方法,它在点击发生的时候改变图片。
在视图(views)和控件(controls)之间存在细微差别。控件是一种特殊版本的视图,它可以响应用户特定的动作。视图用来显示内容,然而空间是用于以某种方式改变内容。一个控件(UIControl)是UIView的子类。事实上,你已经在你的界面中使用过视图(labels,image views)和控件(text fields, buttons)了。