Start Developing iOS Apps (Swift)->使用视图控制器(一)

在本课中,你将继续使用FoodTracker应用的菜品场景的UI。你将重新排列现有的用户界面元素,并使用一个image pikcer(图片选择器)来添加图片到场景。当你完成后,你的应用看上去应该是这样的:


image: ../Art/WWVC_sim_finalUI_2x.png
image: ../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
image: ../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到场景

  1. 打开storyboard,Main.storyboard.
  2. 打开utility area中的Object library。(或者,选择View > Utilities > Show Object Library)。


    image: ../Art/object_library_2x.png
    image: ../Art/object_library_2x.png
  3. 在Object library,在筛选字段输入image view快速找到Image View对象。
  4. 从Object library拖拽一个Image View对象到你的场景,让它在栈视图里面、在按钮下面。


    image: ../Art/WWVC_imageview_place_2x.png
    image: ../Art/WWVC_imageview_place_2x.png
  5. 选择image view后,打开utility area的Size inspector(尺寸检查器)
    当你选择检查器选择器栏左起第五个按钮的时候,Size inspector会出现。它让你可以编辑storyboard中对象的尺寸和位置。


    image: ../Art/WWVC_inspector_size_2x.png
    image: ../Art/WWVC_inspector_size_2x.png
  6. 在Intrinsic Size(内在尺寸)字段,选择Placeholder。(这个字段在Size inspector底部,所以你需要向下滚动来看到)。
  7. 在Width和Height字段都键入320,按下回车键。
    视图的内在内容尺寸(intrinsic content size)是指视图的尺寸是基于视图本身的内容。一个空的image view没有内在内容尺寸。只有你添加一个图片到视图,它的内在内容尺寸才会被设置为图片的尺寸。
    提供占位符尺寸,可以给image一个临时的内在内容尺寸,这样就可以在设计用户界面的时候使用它了。这个值只是在Interface Builder中设计界面的时候有用;在运行的时候,布局引擎会使用视图真实的内在内容尺寸代替。


    image: ../Art/WWVC_placeholdersize_2x.png
    image: ../Art/WWVC_placeholdersize_2x.png
  8. 在画布底部右侧,打开Pin菜单


    image: ../Art/AL_pinmenu_2x.png
    image: ../Art/AL_pinmenu_2x.png
  9. 选择Aspect Ratio(纵横比)旁边的复选框
    这时的Pin菜单看上去是这样的:


    image: ../Art/WWVC_imageview_aspectratio_2x.png
  10. 在Pin菜单中,点击Add 1 Constraints按钮
  11. 在image view选中状态,打开Attribute inspector。
  12. 在Attribute inspector中,找到Interaction(交互)字段,并选择User Interaction Enabled复选框。
    这个功能稍后你会需要,它让你的image view可以和用户交互。

你的场景现在是这样的:


image: ../Art/WWVC_imageview_finalconstraints_2x.png

显示默认照片

添加占位image来让用户知道他们可以和这个image view进行交互来选择一张图片。这张图片可以是从本课最后的可下载文件的Images/文件中的,也可以是你自己的图片。

image: ../Art/defaultphoto_2x.png
image: ../Art/defaultphoto_2x.png

添加一张图片到你的项目

  1. 在project navigator,选择Assets.xcassets来查看asset catalog(资源目录)。
    这个asset catalog是一个为应用存放和组织图片资源的地方。
  2. 在左下角,点击加号(+)按钮,并从弹出菜单中选择(New Image Set)。


    image: ../Art/WWVC_assetcatalog_2x.png
    image: ../Art/WWVC_assetcatalog_2x.png
  3. 双击image set名字,并重命名为defaultPhoto。
  4. 在你的电脑中,选择一张你想添加的图片。
  5. 拖拽并把图片放到image set中的2x插槽中。


    image: ../Art/WWVC_defaultphoto_drag_2x.png
    image: ../Art/WWVC_defaultphoto_drag_2x.png

    2x是本系列课程使用的iPhone 7模拟器的显示分辨率,因此图像在这种分辨率下会看起来最好。

进一步探索
更多关于图片分辨率的信息,查看iOS Human Interface Guidelines中的 Graphics > Image Size and Resolution

将默认的占位图添加到项目,设置image view来显示它。

在image view 中显示一张默认图片

  1. 打开storyboard。
  2. 在storyboard中选择image view。
  3. 选中image view,在utility area中打开Attributes inspector。
  4. 在Attributes inspector中,找到Labeled Image(图片标签) 字段,选择defaultPhoto。

检查点:运行应用。默认图片显示在了image view中。

image: ../Art/WWVC_sim_finalUI_2x.png
image: ../Art/WWVC_sim_finalUI_2x.png

连接Image View到代码

现在,你需要实现在应用运行时改变这个image view中图片的功能。首先,你需要连接image view到ViewController.swift中的代码处。

连接image view到ViewController.swift代码。

  1. 点击Assistant 按钮。


    image: ../Art/assistant_editor_toggle_2x.png
  2. 如果需要更大的空间,点击如下图的按钮。


    image: ../Art/navigator_utilities_toggle_on_2x.png

    你也可以关闭大纲视图。

  3. 在storyboard中,选择image view。
  4. 按住Control键,从画布中的image view拖拽一条线到右侧编辑器的代码上,拖拽到如图所示的位置时,松手。


    image: ../Art/WWVC_imageview_dragoutlet_2x.png
  5. 在出现的对话框中,在Name字段,输入photoImageView。
    剩余的选项保持不变。你的对话框看上去是这样的:


    image: ../Art/WWVC_imageview_addoutlet_2x.png
    image: ../Art/WWVC_imageview_addoutlet_2x.png
  6. 点击连接。
    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)了。

下载文件

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,601评论 4 369
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,367评论 1 305
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,249评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,539评论 0 217
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,967评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,929评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,098评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,825评论 0 207
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,609评论 1 249
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,796评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,282评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,603评论 3 261
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,277评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,159评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,959评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,079评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,874评论 2 277

推荐阅读更多精彩内容