和View Controllers一块儿工做

在这一课中,你会继续在FoodTracker菜谱的场景工做。你会从新安排现有的UI元素并使用图像采集器添加到照片用户界面。当你完成,你的应用程序将是这个样子:android

学习目标swift

在课程结束时,你将可以:app

了解视图控制器的生命周期,如viewDidLoad,viewWillAppear和viewDidAppear这些回调函数
在视图控制器之间传递数据
让一个视图控制器消失
使用手势识别生成一个事件
预测的基于UIView/ UIControl类层次的对象行为
使用asset目录,添加图像资源到项目中编辑器

理解视图控制器的生命周期ide

到目前为止,FoodTracker应用程序有一个单一的场景,其用户界面是由一个单一视图控制器管理。为了打造更复杂的应用程序,你会要处理更多的场景,并须要管理载入和卸载在屏幕上来来去去的Views函数

UIViewController类(及其子类)的对象提供了一组方法,这些方法管理其视图层次结构。当一个视图控制器的状态在转变时,iOS会在适当的时间自动调用这些方法。当你建立一个视图控制器子类,它继承了的UIViewController中定义的方法,让你为每种方法添加本身的自定义行。重要的是要了解,当这些方法被调用,这样你就能够在适当的步骤下设置或拆卸你正在展现的Views,未来你会须要作这些事情。这里能够和Android中的Activity的生命周期作对比布局

UIViewController的方法调用以下:学习

viewDidLoad()----当视图控制器的内容视图(顶层视图)被建立而且从一个storyboard载入后调用。这个方法适用于初始化设置,然而,由于因为APP中的资源限制可能会让views被清除,不能保证这个方法只被调用一次测试

viewWillAppear()---在view可见以前发生的行为。由于一个view的可见度能开关或被其余Views遮蔽,在内容视图出如今屏幕以前,这个方法会当即调用动画

viewDidAppear()---用于view一可见你就想要发生的操做,如获取数据或显示动画。由于一个view的可见度能开关或被其余Views遮蔽,因此这个方法在内容视图出如今屏幕后会当即调用

另外与之对应的还有一套对立的方法存在,如上面状态图所示。

你会在FoodTracker APP中适当的时间内使用一些方法来载入和显示view数据。实际上,若是你有印象,咱们已经写过viewDidLoad()方法中的一些处理

override func viewDidLoad() {
    super.viewDidLoad()
    
    // Handle the text field’s user input through delegate callbacks.
    nameTextField.delegate = self
}

在你的views和数据模型之间,视图控制器做为通讯管道, APP这种设计风格被称为MVC(模型-视图-控制器)。在这个模式中,模型跟踪你的app数据,视图显示你的用户界面,并组成一个内容,控制器管理你的views。经过相应用户的动做而且从数据模型得来的内容以填充view。对于任意iOS app来讲MVC是一个相当重要的好的设计,到目前为止,FoodTracker一直沿用MVC规则构建。在app剩余的设计中,在头脑里保持MVC模式,是时候把基础的UI带到下一水平了,咱们会为菜谱场景建立最终的布局

添加一张菜谱的图片

接下来的是完成菜谱场景的UI,咱们添加一个方法来显示一张具体的菜谱照片。为此,咱们将使用Image View(弄过android的是否是很熟悉?),这里iOS中使用的是UIImageView类,这是一个UI元素用来显示一张图片,步骤以下:

1.打开storyboard,Main.stroyboard

2.打开实用区域的对象库(也能够选择View > Utilities > Show Object Library)

 

3.在对象库中,输入image view来快速过滤出你想要的对象

4.拖动Image View到场景中,在咱们先前按钮控件的下方

 

5.选中ImageView,打开Size inspector,你能够调整ImageView的大小和位置

6.在下方的Intrinsic Size字段,选择Placeholder

7.在上方View和下方的Placeholder中都Width和Height中输入320,而后按下Return,由于一个空的iamge view没有内在大小,你给定image view的placeholder大小,而后能够在界面中指定适当的约束

8.在画布的底部右边,点击Pin按钮


9.选择Aspect Ratio复选框,以下所示:

 

10.在Pin菜单中,点击Add 1 Constraints

你的图片如今是1:1的长宽比,因此他看起来会是个正方形

11.选择image view,打开Attributes inspector

12.在Attributes inspector中,找到Mode而后点击下拉列表,选择Aspect Fill

这个选项有助于确保不一样尺寸的图像在image view中不会失真。

13.在Attributes inspector中,找到Interaction ,而后选中User Interaction Enabled复选框

稍后,你将须要此功能,让用户与image view交互。如今的UI应该以下所示:

显示一个默认照片

用户须要一个指示,让他们知道能够和image view交互,并能选择一张照片。要作到这一点,须要添加一个默认placeholder图像,来传达给用户,他们能选择一个照片


你能够点击这里下载咱们这章所须要的图片。下面让咱们来添加图片到项目中

1.在项目导航中,选择Assets.xcassets(不一样Xcode版本,名字可能不同,有的也许是Images.xcassets)进入asset目录,这个目录是存储你图片的地方

2.在顶部角落,点击+按钮并选择New Image Set

3.而后在出现的Image上,双击,重命名为defaultPhoto

4.在你的电脑中,找到这个图片。

5.而后拖动到x2位置出,放下

2x是 iPhone 6模拟器下的分辨率,图片放在这个位置最佳

接下来咱们要在image view中显示默认图片

a.打开你的storyboard

b.在storyboard中选择image view

c.选中image view的状况下打开Attributes inspector

d.在Attributes inspector中找到Image字段,而后选择defaultPhoto

运行你的APP,效果以下:

 

将Image View链接到代码

如今,你须要实现必要的功能,来在运行时改变图片。你但愿能从代码中改变图片,为此,你首先须要在ViewController.swift中链接image view到代码:

1.点击Assistant打开assistant editor

2.若是你想要更多的工做空间,你能够折叠 project navigator和utility area

3.在storyboard中,选择image view

4.按住Control键拖动image view画布到右边的代码编辑器中,选择outlets,以下图:

 

5.在弹出的对话框中,Name:photoImageView:

6.点击Connect。Xcode会添加必要的代码到ViewController.swift中

你如今能访问iamge view了,从代码上来改变图像,但你如何知道什么时候改变图片?你须要给用户一个方式来告诉他们能够改变图片。例如,点击image view。而后你要定义一个动做方法来处理点击事件。

views和controls之间有微妙的区别,view有一个特定的版原本响应用户的动做。一个视图显示内容,然而control会以某种方式来修改它,一个control(UIControl)是UIView的子类。实际上,你已经使用过了,例如Views(标签,image view),controls(文本框,按钮) 

建立一个手势识别

一个image view不是一个控制,因此它不会像按钮那样被设计为能响应输入。例如,当一个用户点击image view时你不能简单的建立一个动做方法来触发一个事件。(若是你试图按住Control键拖动iamge view到你的代码中,你会发现,在Connection字段后面,它不能选择Action)

幸运的是,它能够很容易的给定一个view添加一个手势识别,做为和控制的能力。手势识别是一个能够附加到view上的对象,view能够响应动做。手势识别能够解释触摸来肯定它们是否对应于特定的手势,诸如滑动,挤压或旋转。你能写一个动做方法,用来处理当手势识别发现它对应的手势时,这正是你须要为image view作的

咱们能够附加一个点击手势识别(UITapGestureRecognizer)到image view中,当一个用户轻击image view时,它将会识别。你能在storyboard轻松搞定这件事。步骤以下:

1.打开Object library

2.输入tap gesture快速过滤出咱们想要的识别事件对象

3.拖动Tap Gesture Recognizer到场景中,放在 image view的上方一点

 

这个Tap Gesture Recognizer会出如今菜谱的场景Dock中

将手势识别链接到代码中

如今链接手势识别到一个动做方法中。步骤以下:

1.按住Control键拖动手势识别到代码编辑器,而后在//MARK:Action放下

 

2.在弹出的对话框中,Connection字段旁,选择Action

3.Name字段旁,输入selectImageFromPhotoLibrary

4.Type旁,选择UITapGestureRecognizer

5.点击Connect或按下Return

建立一个图片选择器来响应用户的轻击事件

那么何时用户会轻击image view,据推测,用户应该能用照片集中选择一个照片。幸运的是,UIImagePickerController已经把这种行为内置到里面了。一个图片选择器控制者管理一个UI,用于拍照并选择保存图像。正如你在文本框工做时须要一个文本框委托同样,你须要一个图片选择控制器委托来帮助你图片选择控制器的工做。这个委托的是一个协议(UIImagePickerControllerDelegate),你在ViewController定义这个图片选择控制器委托对象。首先ViewController须要采用UIImagePickerControllerDelegate协议。由于ViewController将掌管图片选择控制器的展现,同时咱们还须要采用UINavigationControllerDelegate协议,该协议只是让ViewController获取一些基本的导航职责。接下来让咱们添加这两个协议:

1.返回standard editor

2.在项目导航中,选择ViewController.swift

3.在ViewController.swift中,找到class这行:

class ViewController: UIViewController, UITextFieldDelegate {

4.而后添加以下代码:

class ViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

接下来咱们须要实现selectImageFromPhotoLibrary()方法了

a .在ViewController.swift中找到selectImageFromPhotoLibrary()动做方法

@IBAction func selectImageFromPhotoLibrary(sender: UITapGestureRecognizer) {
}

b.在方法体中,添加以下代码:

// Hide the keyboard.
nameTextField.resignFirstResponder()

该方法是确保,用户在点击image view时,若是软键盘正输入打开状态,须要关闭它

c.添加代码,来建立一个图片选择控制器

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

d.而后添加这行代码:

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

这行代码是设置图片选择控制器的源,或者是它获取图片的地方。.PhotoLibrary选项表示使用模拟器的相机胶卷,这个imagePickerController.sourceType是UIImagePickerControllerSourceType中的一个类型。它是一个枚举。意思是你能写缩写形式.PhotoLibrary来代替UIImagePickerControllerSourceType.PhotoLibrary

e.添加以下代码设置图片选择控制器的委托为ViewController:

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

f.最后加上这一行

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

presentViewController(_:animated:completion:)是ViewController中调用的方法,虽然这个方法没有显式的写入,但方法会在隐式的self对象上执行。改方法询问ViewControllerto出示imagePickerController定义的视图控制器,animated为true表示图像选择控制器是否以动画呈现。completion表示当此方法执行完后,执行一个关包。由于不须要作任何事,因此这个参数传nil便可。你完整的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)
}

在图片选择控制器展示完后,它的行为会交给委托。给用户选择图片的能力,你须要实现UIImagePickerControllerDelegate中的两个委托方法

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

其中第一项,imagePickerControllerDidCancel(_:),让你获得当用户点击图片选择器的取消按钮的调用。这种方法给你一个机会让UIImagePickerController消失。实现以下:

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

第二项,imagePickerController,当用户选择一个照片时调用。这种方法可让你有机会在用户从选择器中选择一个或多个图像时作些什么。在本例中,咱们会采起选定的图像,并在UI中显示。实现以下

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)
}

第一行代码表示info字典包含你选中原始图像,若是存在,是已编辑的图片版本。为了简单,咱们将使用原始的,未经编辑的图片做为菜谱照片。咱们把这个照片存储在selectedImage常量中。

第二行代码表示咱们给前面的场景中的image view设置它的image

第三行代码固然是让图片选择器消失啦

检查点:运行你的应用程序。你应该能够点击Image View 查看图像选择器。系统会有一个权限警告,询问许可给FoodTracker应用程序访问照片,点击OK便可。而后,您能够点击取消按钮关闭选择器,或打开相机胶卷并单击图像来选择它,并在Image View中显示

 

若是你经过在模拟器中发现没有任何照片的话。你能够直接添加本身的图像到模拟器来测试。前面Image View中的默认图文件夹中,附带了一张菜谱的图片。你把图片直接从电脑上拖入模拟器便可

相关文章
相关标签/搜索