您的位置:首页 > 移动开发 > Swift

IOS Apps 开发(Swift)(5)——Work with View Controllers

2016-02-25 21:20 676 查看
前言:网上一直没有找到用Swift开发IOS的好的教程,所以找了官网的文档翻译一下算了。如有错误欢迎指正。博主首发CSDN,mcf171专栏。
博客链接:mcf171的博客
原文链接:Work
with View Controllers
——————————————————————————————
在本次课程中,我们还是在对FoodTracker app的菜品场景的UI进行处理。我们会重新安排存在的UI元素并且添加一个图片选择器来给UI添加图片。当完成的时候app应该如下图



学习目标
在本次课程中,你可以了解到:

理解view controller的生命周期,并且理解什么时候发生回调。不如说viewDidLoad,viewWillAppear和viewDidAppear
在两个view controllers之间传输数据
移除view controller
使用手势识别作为产生时间的一个额外层次
基于UIView/UIControl类层次结构操作对象的行为
使用asset catalog向工程添加图片资源

理解ViewController的生命周期

到目前为止,FoodTracker app还是一个单一场景的,被一个view controller管理。当我们构建更复杂的app的时候我们会处理更多的场景,我们需要在场景出现和退出屏幕的时候管理加载和卸载视图。

一个UIViewController类或者子类的对象有一些列的方法来管理他的视图层次结构。当view controller在状态之间转换时,iOS自动在合适的时间调用这些方法。当穿件一个 view controller 的子类时(比如ViewController 类)的时候,它会集成在UIViewController中定义的方法,并且对于每个方法我们可以定义我们自己的用户行为。因此知道在什么时候这些方法在什么时候被调用时非常重要的。



UIViewController方法的调用如下:

viewDidLoad()——当view controller 的内容视图(在视图层次最上面)被创建并从一个storyboard中加载的时候调用。这个方法是为初始步骤进行准备的。然而因为app的资源是有限的,视图可能被释放了,因此不能保证这个方法仅被调用一次。
viewWillAppear()——这个方法是为了你想在视图可视化之前做一些操作的时候做准备的。因为一个视图可视化可能是被其他视图覆盖了,因此这个方法在这个内容视图出现在屏幕上的时候总会马上调用。
viewDidAppear()——这个是当视图可视化的时候,为我们想做一些操作而准备的。比如说延迟显示数据或者展现一个动画。因为一个视图可视化可能被其他视图遮挡,所以这个方法会在内容视图出现在屏幕之后马上被调用

当然与之对应的一系列销毁的方法也是有的,正如在上面的状态转换图所示的。
我们能够使用FoodTracker app中一系列的方法来加载和显示视图数据。事实上,如果你还能想起我们在viewDidLoad()方法中写的代码话。

override func viewDidLoad() {
super.viewDidLoad()

// Handle the text field’s user input through delegate callbacks.
nameTextField.delegate = self
}


这个app的风格设计就像我们熟知的MVC结构——视图控制器是我们视图和数据模型之间的交互管道。在这个模式下,模型保留我们app的数据,师徒展现我们的用户接口,展现我们app的内容,控制器则管理我们的视图。通过对用户行为进行响应,同时将数据模型中的内容展现在视图上,控制器就成了模型和视图交互的大门。MVC对于任何的iOS app来说都是一个极其重要额设计框架。到目前为止 我们的FoodTracker app都遵循了MVC的准则。

在接下来的app设计中我们希望大家把MVC模式谨记心中。是时候进一步提升我们基础的UI了。让我们完成最钟的菜品场景的布局

增加一个菜品照片

菜品场景下一步需要完成的步骤是增加一个方式来展现具体菜品的图片。为了达到这个效果我们需要加入一个image view(UIIMageVIew)。这个UI 元素是用来展现一个图片的。
增加image View 到场景中

1、打开storyboard——Main.storyboard

2、打开实用工具区的对象库(可选方案为View > Utilities > Show Object Library)



3、在对象库中搜索框中输入 image view
4、将Image View从对象库中拖入场景中,使它的位置位于stack view中按钮的下方



5、选中image view。打开实用工具区的尺寸查看器



6、在Intrinsic Size 的属性值中,选择Placeholder

7、输入320的长和宽

一个空的image view 不会有 固定内容尺寸(intrinsic content size)。我们给我image view一个占位符尺寸从而可以指定合适的约束。



8、在画布的右下角打开Pin 按钮



9、选择Aspect Ratio边上的多选框。



10、在 Pin 菜单点击增加Add 1 Constraints 的按钮



现在image view 是1:1的长宽比。因此它看上去总是一个正方形。

11、选中image view打开属性查看器

12、在属性查看器找到labeled Interaction的属性,然后选择 User Interaction Enabled 的单选框。

之后将会用到这个属性来让用户和image view进行交互

现在我们的UI看起来应该是这样



展现默认的照片

当用户和 image view 进行交互来选择照片时,用户需要一个提示信息。为了完成这个功能,我们需要增加一个默认的占位符图片从而告诉用户他可以选择一个照片



你可以先下载本课程最后的文件然后从Images的文件夹中获取这个图片

为工程添加图片

1、在工程导航栏选择Assets.xcassets来查看资源目录

这个资源牡蛎是用来存储和管理app的图片资源的。

2、在左下角点击+号按钮选择一个新的图片



3、双击图片集名称重命名为defaultPhoto

4、在电脑上找到想添加的图片

5、将图片拖拽到2x的框中



2x是为iPhone6 模拟器准吗的展示解决方案,因为会在之后的课程也会用到,所以这个图片最好放在这里。

有了默认的占位符图片,那么我们就可以设置image view 来展示它了。

在 image view 中展示默认的图片

1、打开storyboard

2、选择 image view

3、 打开属性查看器

4、 找到Image属性 选择defaultPhoto

里程碑:运行app 默认图片在 image view 中展现



将Image View 和 代码联系起来
现在我们需要实现在运行的时候,可以改变 image view 中的图片。首先我们需要做的是将 image view 和我们的控制器关联起来。
关联 image view 和 ViewController.swift
1、点击助手按钮来打开诸侯编辑器



2、如果想要更大的工作空间可以折叠工程导航和实用工具区。



3、选择 image view

4、control + 拖拽的方式将 image view 从画布上拖到存在的outlets的最下面代码。



5、在弹出的对话框输出名字:photoImageView



6、点击Connect

在Xcode中将出现以下代码

@IBOutlet weak var photoImageView: UIImageView!


现在我们可以通过代码来访问 image view 从而改变他的图片,但是我们不知道什么时候改变图片,所以我们需要给用户一个方式来表明他们想要改变图片——比如说通过点击 image view。因此我们需要定义一个动作方法来改变图片,当这个点击事件发生的时候。

在视图和控制器其实有一个微妙的区别,这里值的视图和控制器是指在画布上UI元素由于不同角色所决定是视图还是控制器,比如说 标签和 imag view 就是视图,但是文本框和按钮就是控制器。用户可以查看按钮的父类就是UIControl ,但是这个也是UIView的子类。所以说UIControl只是比较特殊的UIView

创建一个手势识别器
image view 不是控制器,所以他不能像button那样去设计来响应用户的事件。换句话来说你不能通过简单的创建一个 动作方法来接受当用户点击 image view 的消息。同时当你使用Control + 拖拽的方法的时候也应该注意到不能够选择Action。

但是同样也有容易的方法使得 view也有相同的功能,那就是创建手势识别器。手势识别器也是一个对象,它允许当用户触碰一个视图的时候像一个控制器一样对用户行为进行响应。手势识别通过识别触碰的方式来了解对应的是什么手势——比如说猛戳、旋转等。这样就可以通过识别一个手势来触发一个动作方法了,这也是 image view 所需要的。
给 image view 增加一个点击手势(UITapGestureRecogizer),这个可以识别用户是否在点击 image view。
增加一个点击手势识别
1、打开对象库
2、在对象库中搜索 tap gesture

3、将tap gesture Recognize 对象拖拽到 image view 上面



这个 点击手势识别器将出现在场景 dock 的上方



将手势识别器和代码相关联
接下来我们需要做的就是将手势识别器和代码中的一个action方法进行关联
连接手势识别器和代码
1、使用control + 拖拽的方式 将手势识别器拖到 action 注释的下面



2、在出现的对话框中选择Action

3、名字为:selectImageFromPhotoLibrary

4、类型选择:UITapGestureRecognize



5、点击连接

Xcode 将增加以下代码

@IBAction func selectImageFromPhotoLibrary(sender: UITapGestureRecognizer) {
}


创建一个图片选择器
那么当用户点击了 image view 的时候会发生什么呢?我们可以先猜想以下,用户应该需要能从图片库里面选一张照片,然后选取其中的一个。我们所想的这些动作UIImagePickerController 类都可以做到。一个图片挑选器控制管理了一个挑选图片并且将图片保存到app里面的功能。就像我们需要一个文本框代理一样,我们也需要一个图片选择器代理来处理图片选择的控制。这个代理接口的名字是UIImagePickerControllerDelegate,代理者就是我们的ViewController

首先ViewController需要采用UIImagePickerControllerDelegate接口。因为ViewController会被 image picker controller接管,所以我们还需要引入UINavigationControllerDelegate接口,这个能让ViewController承担一些基本的导航响应。
引入两个接口
1、点击标准按钮返回标准编辑器,同时展开工程导航和实用工具区



2、在工程导航中选择ViewController.swift

3、在ViewController.swift中找到class这一行。

class ViewController: UIViewController, UITextFieldDelegate {


4、在UITextFieldDelegate后面加逗号,同时引入两个接口

class ViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {


接下来我们需要返回之前定义的动作方法selectImageFromPhotoLibrary并且进行实现

实现selectImageFromPhotoLibrary的动作方法

1、在ViewController.swift中找到selectImageFromPhotoLibrary动作方法。

2、在方法中添加如下代码

// Hide the keyboard.
nameTextField.resignFirstResponder()


这个代码保证了当用户点击了文本框之后如果点击了 image view 这个键盘会消失。

3、增加下面的 image picker controller

// UIImagePickerController is a view controller that lets a user pick media from their photo library.
let imagePickerController = UIImagePickerController()


4、增加下面的代码
// Only allow photos to be picked, not taken.
imagePickerController.sourceType = .PhotoLibrary


上面这行代码设置了 image picker 控制器的源或者说从哪里得到图片,.PhotoLibrary 是使用了模拟器的相机。

imagePickerController.sourceType 是 UIImagePickerControllerSourceType,这也是一个枚举类型。因此可以写成缩写形式 .PhotoLibrary 而不是UIImagePickerControllerSourceType.PhotoLibrary。

5、在上一行下面再加一行

presentViewController(imagePickerController, animated: true, completion: nil)


(下面一段话楼主也没太懂,也就不翻译全了)

presentViewCOntroller方法是被ViewController调用的,尽管他没有明确的写出来,但是它会被一个隐式的self对象执行。这个方法要求ViewController呈现 imagePickerController定义的试图控制器。

因此selectImageFromPhotoLibrary最终形式应该是

@IBAction func selectImageFromPhotoLibrary(sender: UITapGestureRecognizer) {
// Hide the keyboard. nameTextField.resignFirstResponder()

// UIImagePickerController is a view controller that lets a user pick media from their photo library. let imagePickerController = UIImagePickerController()

// Only allow photos to be picked, not taken. imagePickerController.sourceType = .PhotoLibrary

// Make sure ViewController is notified when the user picks an image.
imagePickerController.delegate = self

presentViewController(imagePickerController, animated: true, completion: nil)
}


当一个 image picker 控制器 被提出时,他的行为就脱离了他的代理器。为了让用户可以选择一张图片,我们需要实现两个在UIImagePickerCOntrollerDelegate代理方法。

func imagePickerControllerDidCancel(picker: UIImagePickerController)
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])


第一个方法是当用户点击 image picker的取消按钮的时候会被调用。第二个方法我们可以不管。

实现 imagePickerControllerDidCancel方法

1、在ViewController.swift中 //MARK:Actions的上面加入下述注释

// MARK: UIImagePickerControllerDelegate


2、增加以下方法

func imagePickerControllerDidCancel(picker: UIImagePickerController) {
}


3、在方法中增加代码

// Dismiss the picker if the user canceled.
dismissViewControllerAnimated(true, completion: nil)


最终imagePickerControllerDidCancel看起来的是

func imagePickerControllerDidCancel(picker: UIImagePickerController) {
// Dismiss the picker if the user canceled. dismissViewControllerAnimated(true, completion: nil)
}


第二个需要实现的UIImagePickerControllerDelegate方法是 imagePickerController,当一个用户选择一个照片的时候方法会被调用。这个方法能够让我们对于用户从Picker中选择的照片进行处理。在我们这个例子中我们将把选中的照片放在 UI中展示

实现imagePickerController方法

1、在imagePickerControllerDidCancel方法下增加下述方法

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
}


2、在这个方法中加入代码

// The info dictionary contains multiple representations of the image, and this uses the original.
let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage


这个info 字典包含了在picker中选中的原始的照片,和这个被编辑的照片。为了简单,我们使用原始的,没有被编辑图片

3、设置
image view 的outlet 来展现选中的图片

// Set photoImageView to display the selected image.
photoImageView.image = selectedImage


4、忽略 image picker

// Dismiss the picker.
dismissViewControllerAnimated(true, completion: nil)


最终 imagePickerController方法应该看起来是

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
// The info dictionary contains multiple representations of the image, and this uses the original. let selectedImage = info[UIImagePickerControllerOriginalImage] as! UIImage

// Set photoImageView to display the selected image. photoImageView.image = selectedImage

// Dismiss the picker. dismissViewControllerAnimated(true, completion: nil)
}


里程碑:运行app, 我们应该可以点击 image view 然后拉出一个 image picker。我们需要点击Ok从而允许我们的FoodTracker访问 相册,当然沃恩也可以点击取消按钮来护士picker 或者打开相册来选择一个图片展示在 image view中



我们可以注意到在我们的相册中没有任何食物的图片,因此我们可以直接添加我们自己的图片到模拟器中,同样你可以下载在本课程最后的文件,然后在Images文件夹中找到图片资源,或者使用你自己的

往模拟器中添加图片

1、在模拟器中运行app

2、在电脑中选择想添加的图片

3、将图片拖到模拟器中



模拟器会打开相册App然后显示刚刚添加的照片


里程碑:运行app,你应该可以点击image view然后在相册中选中一张食品的图片。

ps: 样例文件 Download File
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: