第九章:相机、相册和社交网络

在这一章节中,你将学会如何在应用中添加相机功能,还会学会如何从相册中获取图片和视频,最后,将学会如何给应用增加分享到Facebook和Twitter的功能。这一章将教会你Swift语言中最重要一部分,这样你能够更快的开发你的App。苹果公司提供了简单快速的方法来把相机图片和分享设计网络集成到一起。

UIImagePickerController

苹果提供了一个简单的类来处理图片和视频。图9-1中的UiImagePickerController看起比较眼熟,被广泛的使用在很多iOS App中。UiImagePickerController能够让相机中的景象直接显示在App中,UiImagePickerController还能够展示相册中的图片,让用户选择图片或者视频。

UiImagePickerController是一个简单的界面,直接在另外的view controller(视图控制器)中模式展示(presented modally)(presented modally是一个Segue类型)。一个modal view controller直接在当前的view controller中显示,有点像是弹出框。modal view controller会从下方滑出,而且只能由用户关闭才能返回之前的界面。modal view controller只能用在临时的交互或者短期的交互中。

Page 235

创建UiImagePickerController对象和创建其他对象一样,首先声明一个变量,然后调用初始化:

var imagePicker = UIImagePickerController()

Cameras(相机)

在使用UiImagePickerController之前需要先检查一下当前设备的相机是否可用,在某些情况下,设备虽然有相机但是是不能用的。检查设备相机是否可用的代码:

if UIImagePickerController.isSourceTypeAvailable(.Camera) {
    //Camera is Available
} else {
    //Camera not Available
}

如何相机可用,则可以设置UiImagePickerController来调用相机获取拍摄图片或者视频。把UiImagePickerController设置成相机模式,需要把sourceType属性设置为.Camera

imagePicker.sourceType =  .Camera

Page 236 | Chapter 9 : Camera, Photos, and Social Networks

很多iOS设备有前后两个摄像头。检查前置摄像后可用还是后置摄像头可用,我们使用isCameraDeviceAvailable这个方法。把摄像头的位置传给isCameraDeviceAvailable,然后这个方法就会返回true或者false:

if UIImagePickerController.isCameraDeviceAvailable(.Front) {
    //Front Camera Available
} else {
    //Front Camera Not Available
}

if UIImagePickerController.isCameraDeviceAvailable(.Rear) {
    //Rear Camera Available
} else {
    //Rear Camera Not Available
}

如何当前设备没有可用的摄像头,UiImagePickerController可以让用户从相册中选择图片或者视频。把sourceType属性设置成.PhotoLibrary就可以展示选择图片界面了:

imagePicker.sourceType =  .PhotoLibrary

在iOS模拟器中测试App有时候会有局限性,因为模拟器没有摄像头。永远不要假设设备有相机,总是检查是否有摄像头。为了测试摄像头功能,你必须在真机上运行应用,在真机上运行应用的知识我们将会在第十章进行详细的介绍。

Media Types (媒体类型)

媒体的类型可以设置为图片、视频、和图片+视频。默认设置是图片+视频。想要改变这个设置,需要引入Mobile Core Services framework(Mobile Core Services框架)。

首先点击Project Navigator中的工程名称,显示工程的详细信息,然后滑到底部,找到Linked Frameworks and Libraries这部分,点击左下角的加号,在搜索框中输入MobileCoreServices,选择MobileCoreServices.framework,点击Add按钮。

这样MobileCoreServices.framework文件就添加到你的Project Navigator中了,接着你需要在代码中添加这行代码:

import MobileCoreServices

有了这行代码,MobileCoreServices.framework类就会添加到你代码中,你可以使用这个框架了。下面是每个媒体类型的关键词:

UIImagePickerController | Page 237

kUTTypeImage 相片和图片 kUTTypeMovie 电影和视频 用数组来设置mediaTypes属性,可以存数合适的数值。例如:

imagePicker.mediaTypes = [kUTTypeImage]
//只能拍摄或选择图片
imagePicker.mediaTypes = [kUTTypeMovie]
//只能拍摄或选择视频

Editing(编辑)

苹果甚至提供了缩放图标和修剪视频的功能,叫做editing controls ,把allowsEditing属性设置为true就能开启这些功能了。例如:

imagePicker.allowsEditing = true

这样就能进入编辑界面,你还能获取到编辑后和编辑前的媒体。

Delegates (委托)

UiImagePickerController提供了一些用户基本交互操作的委托更新(delegate updates)(这里不确定delegate updates的翻译是否正确)。例如当用户存储一个新的媒体时,就触发了一个delegate updates。为了能够收到这些updates,我们需要把UiImagePickerController委托到当前的view controller,使用self关键词来表示当前的view controller。例如:

imagePicker.delegate = self

当然,我们还要保证当前的view controller已经遵从了UiImagePickerController协议,遵从协议的方法很简单,就在当前的view controller中添加这行代码:

class ViewController: UIViewController, UIImagePickerControllerDelegate {

因为UiImagePickerController继承自UINavigationController,所以还要遵从UINavigationController协议,这份协议提供UINavigationController如push和pop等事件的updates,你的view controller必须要遵从协议,但是协议中方法(methods)都是可选的。详见代码:

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

Page 238 | Chapter 9 : Camera, Photos, and Social Networks

Working with Images

UIImagePickerControllerDelegate有两个方法来处理媒体,第一个方法是imagePickerController(_: didFinishPickingImage),当相机拍摄了一张图片或者从相册中选择了一张图片后,这个方法就会触发delegate。如果用户是创建或选择的视频,那么这个方法不会被调用。这个方法提供了UIImage参数,来包括新创建的图片。为了能够出发这个事件,我们需要添加下列代码:

func imagePickerController(picker: UIImagePickerController!,didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!){

}

Working with Multiple Media Types

第二个方法更高级一些,是imagePickerController(_:, didFinishPickingMediaWithInfo _:),当用户创建选择了图片视频,这个方法会触发委托。如果sourceType设置为.PhotoLibrary,那么这个方法会在用户选中图片或视频后被调用;如果sourceType设置为.Camera,用户拍摄了图片或视频并且确认保存后,这个方法才会被调用。info参数值为新图片视频提供了额外的信息。 添加下列代码可激活这个事件:

func imagePickerController(picker:UIImagePickerController,didFinishPickingMediaWithInfo info: [NSObject : AnyObject]){
     //media selected
}

info参数还包括mediaType变量,在获取图片视频之前,需要先检查mediaType,获取info参数中的键(key)UIImagePickerControllerMediaType就可以检查mediaType了:

var mediaType = info[UIImagePickerControllerMediaType]

info字典类型参数里面包含了很多关于新拍摄或选择图片视频的信息,下面这些键(key)将会提供所选内容的具体值:

UIImagePickerControllerMediaType Media type媒体类型,类如:kUTTypeImage 或者 kUTTypeMovie

UIImagePickerControllerOriginalImage 原始未裁剪的图片

UIImagePickerControllerEditedImage 编辑过的图片,只有allowsEditing设置为true

UIImagePickerController | Page 239

UIImagePickerControllerCropRect 将原始图片矩形裁剪

UIImagePickerControllerMediaURL 视频在本地文件中的路径(仅限视频)

UIImagePickerControllerReferenceURL 用于高级视频框架的URL(URL used with advanced video framework)

UIImagePickerControllerMediaMetadata 仅限图片,字典中图片的元数据(Photos only, dictionary full of metadata for image)

所有的这些键都能获取到媒体的更多信息,最常用的键是UIImagePickerControllerMediaType , UIImagePickerControllerOriginalImage , 和 UIImagePickerControllerMediaURL

mediaType覆盖后,运行if语句来检测是图片还是视频(这话原话是Once the mediaType has been recovered, run it through an if statement to detect if itis a video or a photo.我不知道recovered在这里应该如何翻译啊……)。例如:

var mediaType = info[UIImagePickerControllerMediaType! as NSString]
if mediaType == kUTTypeImage as NSString {
    //photo
} else if mediaType == kUTTypeMovie {
    //video
} else {
    //error/missing
}

Images with didFinishPickingMediaWithInfo

如果mediaType的类型是图片,那么图片的会直接传入到 info参数中,新图片会直接从字典中提取出来放入到UIImage,UIImage这个类是用来存储图片的,UIImage的图片传给UIImageView,UIImageView就像是相片的相框,它能把图片装裱起来,图片也能随时更换 UIImageView在用户界面上展示UIImage的内容。例如:

var myImage = info[UIImagePickerControllerOriginalImage] as UIImage

把图片放入UIImageView的方法:把UIImageView的image属性设置为UIImagePickerControllerOriginalImage的键:

imageView.image = myImage

Page 240 | Chapter 9 : Camera, Photos, and Social Networks

Video in didFinishPickingMediaWithInfo

如果mediaType的类型是视频,视频不会直接存储到字典中,而是存储视频文件的路径,用 UIImagePickerControllerMediaURL键来获取。获取路径而不是直接获取视频,有一个非常大的好处,能够节省电量和内存。视频路径可以传递给MPMoviePlayerViewController,在用户屏幕上播放。获取视频的代码:

var videoPath = info[UIImagePickerControllerMediaURL as NSURL

MPMoviePlayerViewController这个类能够让开发视频播放的工作更简单,给MPMoviePlayerViewController一个视频路径,就能播放视频,也能在播放过程中做一些简单的操作。MPMoviePlayerViewController需要Media Player framework这个框架。

首先点击Project Navigator中的工程名称,显示工程的详细信息,然后滑到底部,找到Linked Frameworks and Libraries这部分,点击左下角的加号,在搜索框中输入MediaPlayer,选择MediaPlayer.framework,点击Add按钮。

这样MediaPlayer.framework文件就添加到你的Project Navigator中了,接着你需要打开view controller,然后把鼠标放到import UIKit下方,然后添加这行代码:

import MediaPlayer

这行代码会把MediaPlayer.framework类引入到当前代码中,MediaPlayer.framework中包括MPMoviePlayerViewController这个类。

接着,和创建其他的对象一样,创建一个MPMoviePlayerViewController,接着设置它的contentUIRL属性:

var videoPath = info[UIImagePickerControllerMediaURL as NSURL]
var myMoviePlayerViewController = MPMoviePlayerViewController()
myMoviePlayerViewController.moviePlayer.contentURL = videoPath

Presenting UIImagePickerController

展示新的view controller,我们使用presentViewController这个方法:

self.presentViewController(imagePicker, animated: true, completion: nil)

UIImagePickerController | Page 241

Integrating with Social Networks (加入社交网络功能)

在很多手机应用中,把内容分享到社交网络上已经成为一个核心的特性,然而,把所有的社交网络都整合到App中会非常花费时间,苹果公司提供了Social framwork让开发分享功能更简单。Social framework中包括SLComposeViewController,SLComposeViewController这个类可以让用户把内容分享到Twitter和Facebook。SLComposeViewController使用用户在iPhone设置中填写的登录帐号密码,这就说明开发者不必自己写代码就可以分享到Facebook和Twitter了,用户可以分享文字、链接甚至是图片。

在使用SLComposeViewController之前,我们需要先把Social framework引入到工程当中。首先点击Project Navigator中的工程名称,显示工程的详细信息,然后滑到底部,找到Linked Frameworks and Libraries这部分,点击左下角的加号,在搜索框中输入Social,选择Socail.framework,点击Add按钮。这样Social.framework文件就添加到你的Project Navigator中了,接着你需要打开view controller,然后把鼠标放到import UIKit下方,然后添加这行代码:

import Social

Setting the Social Network (设置社交网络)

上面这行代码会把Social framework引入到view controller中,使SLComposeViewController可以在代码中使用了。在创建SLComposeViewController时需要提供serviceType,serviceType类型有两个选项: SLServiceTypeFacebook Facebook SLServiceTypeTwitter Twitter

首先要核实需要的service是否可用,使用isAvailableForServiceType(_: )来检查service类型在当前设备是否可用:

if (SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook)) {
     //Facebook available
}

我们可以使用_(forServiceType:)方法来创建SLComposeViewController,有一个forServiceType参数:

if (SLComposeViewController.isAvailableForServiceType(SLServiceTypeFacebook)) {
       //Facebook available
      var myComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
}

Page 242 | Chapter 9: Camera, Photos, and Social Networks

Setting the Initial Text (设置默认文案)

你还可以给SLComposeViewController设置默认文案,这段默认文案会出现分享界面,提前给用户写好,用户可以直接就分享出去,当然也可以删除或者修改文案。我们用setInitialText(_:)方法来创建默认文案:

var myComposeViewController = SLComposeViewController(forServiceType: SLServiceTypeFacebook)
myComposeViewController.setInitialText("I love this app!")

Adding Images (增加分享图片)

SLComposeViewController也支持图片分享,使用addImage(_:)方法,这个方法有一个UIImage参数:

myComposeViewController.addImage(myImage)

Adding URLs

如果不能分享链接那么分享就没有意义了,SLComposeViewController当然支持分享URL,使用addURL(_:)方法,接收NSURL作为参数。NSURL和字符串非常相似,专门为UIL和文件路径使用。例如:

var myURL = NSURL(string: "http://www.google.com")
myComposeViewController.addURL(myURL)

Presenting SLComposeViewController

最后,SLComposeViewController创建并且设置完成后,需要把SLComposeViewController呈现给用户了,我们使用modally present这个呈现方式,使用presentViewController(_:,animated: completion: )方法,例如:

self.presentViewController(myComposeViewController,animated: true, completion: nil)

这样SLComposeViewController就会展示在用户面前,用户分享内容。如果用户还没有登录社交网络,iOS会引导他到设置中的登录界面完成操作。

现在是时候把知识应用到实践中去了,来创建一个自拍照App吧。

Integrating with Social Networks | Page 243