在IOS中使用swift调用系统相机
在IOS的APP开发中,很容易就会遇到使用拍照或录制视频的功能.如果要求并不是太多的话,最简单方式就是调用系统自带的图像获取器UIImagePickerController
.
由于UIImagePickerController
继承自UINavigationController
,所以它的delegate
需要实现UIImagePickerControllerDelegate
和UINavigationControllerDelegate
两个协议.
基本知识
要使用这个类主要要做以下几件事情:
- 首先要创建一个全局的
UIImagePickerController
实例. - 判断设备是否支持数据来源:
UIImagePickerController.isSourceTypeAvailable(.Camera)
UIImagePickerController.isSourceTypeAvailable(.PhotoLibrary)
UIImagePickerController.isSourceTypeAvailable(.SavedPhotosAlbum)
然后指定数据的来源.一共有三种来源:
UIImagePickerControllerSourceType.PhotoLibrary
来自系统图库UIImagePickerControllerSourceType.Camera
来自相机UIImagePickerControllerSourceType.SavedPhotosAlbum
来自相册
如果数据来源是相机,那么还需要设置相机的捕获模式
cameraCaptureMode
. 主要分为.Photo
和.Video
实现各种代理方法接收保存和获取图像的方法.
设置媒体类型,
UIImagePickerController
根据这个的值来决定选择或拍摄的媒体类型.这个是一个[String] 字符串数组.多个值就表明了可以在拍摄的界面上切换.需要注意的是这个mediaTypes
的定义是在MobileCoreService
框架下的.当然也可以直接使用String
的常量来描述.常用的媒体类型为:
常量名 | 常量值 | 说明 |
---|---|---|
kUTTypeImage | public.image | 照片 |
kUTTypeMovie | public.movie | 音视频 |
kUTTypeVideo | public.video | 纯视频 |
kUTTypeAudio | public.audio | 纯音频 |
kUTTypeLivePhoto | com.apple.live-photo | IOS9的动态照片(关于动态图片后面再单独开博文来说) |
除了上面说的几个设置外,在使用UIImagePickerController
过程中可能还用得到的设置主要有:
- modalTransitionStyle: 取景框出现效果
- allowsEditing: 是否允许编辑,只有在
showsCameraControls
属性为true
时才有效 - showsCameraControls: 是否显示拍照时的工具栏,如果要自定义拍摄界面,需要把这个工具栏隐藏掉
- videoMaximumDuration: 录制视频的时长, 默认是10秒
- videoQuality: 视频质量,枚举定义在
UIImagePickerControllerQualityType
中 - cameraDevice: 前置,还是后置摄像头,枚举定义在
UIImagePickerControllerCameraDevice
- cameraFlashMode:闪光灯模式,枚举定义在
UIImagePickerControllerCameraFlashMode
有了这些准备,就可以开始来实现一个最简单的DEMO了.
Demo
DEMO很简单,在一个APP上增加一个按钮,点击这个按钮,打开系统自带的摄像头.然后可以进行拍摄,最后把拍摄结果保存到相册中.
首先先创建一个
UIImagePickerController
:1let imagePickerController:UIImagePickerController = UIImagePickerController()给某个ViewController上增加
UIImagePickerControllerDelegate
和UINavigationControllerDelegate
两个协议.123456class ViewController: UIViewController,UIImagePickerControllerDelegate,UINavigationControllerDelegate {override func viewDidLoad() {imagePickerController.delegate = self}...}然后设置PickerController的初始值:
1234567imagePickerController.modalTransitionStyle = .FlipHorizontalimagePickerController.allowsEditing = true //是否允许编辑imagePickerController.sourceType = .Camera //数据来源为摄像头imagePickerController.videoMaximumDuration = 15 //模式录制视频长度,单位秒imagePickerController.mediaTypes = ["public.image","public.movie"] //允许的相机类型(拍照,摄像....)imagePickerController.videoQuality = .TypeHigh //视频质量imagePickerController.cameraCaptureMode = .Photo //初始摄像头的模式设置界面按钮的事件响应,在相应中增加打开
imagePickerController
视图的方法:12self.presentViewController(imagePickerController, animated: true) { () -> Void in}实现完成照片或视频的拍摄回调代理方法:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
:1234567891011121314151617181920212223242526func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {//获取媒体的类型let mediaType = info[UIImagePickerControllerMediaType] as! String//如果媒体是照片if mediaType == kUTTypeImage as String {//获取到拍摄的照片, UIImagePickerControllerEditedImage是经过剪裁过的照片,UIImagePickerControllerOriginalImage是原始的照片let image = info[UIImagePickerControllerEditedImage] as! UIImage//调用方法保存到图像库中UIImageWriteToSavedPhotosAlbum(image, self,"image:didFinishSavingWithError:contextInfo:", nil)}else {//视频//获取到视频的临时路径let urlStr = (info[UIImagePickerControllerMediaURL] as! NSURL).path//启动异步线程保存视频到图像库中dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { () -> Void in//调用方法保存到图像库中UISaveVideoAtPathToSavedPhotosAlbum(urlStr!, self, "video:didFinishSavingWithError:contextInfo:", nil)})}//关闭照相框self.dismissViewControllerAnimated(true, completion: nil)}实现完成保存后的结果回调方法
func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>)
:1234567891011func image(image: UIImage, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>) {if error == nil {let ac = UIAlertController(title: "Saved!", message: "成功保存照片到图库", preferredStyle: .Alert)ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))presentViewController(ac, animated: true, completion: nil)} else {let ac = UIAlertController(title: "Save error", message: error?.localizedDescription, preferredStyle: .Alert)ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))presentViewController(ac, animated: true, completion: nil)}}实现完成保存视频后的结果回调方法
func video(videoPath: String, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>)
:1234567891011func video(videoPath: String, didFinishSavingWithError error: NSError?, contextInfo:UnsafePointer<Void>) {if error == nil {let ac = UIAlertController(title: "Saved!", message: "成功保存视频到图库", preferredStyle: .Alert)ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))presentViewController(ac, animated: true, completion: nil)} else {let ac = UIAlertController(title: "Save error", message: error?.localizedDescription, preferredStyle: .Alert)ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))presentViewController(ac, animated: true, completion: nil)}}
这样就完成了打开系统相机,并把拍摄的结果放入系统默认的相薄中的全部功能了.
自定义相薄
到目前为止照片等都是保存到系统默认的相机胶卷
这个相薄中. 但是像QQ
微信
这些应用都是可以把图片存放到自己的相薄中的.这就要求程序中对相薄进行操作了.
在IOS9中,要操作相薄的话,需要引入import Photos
库.然后使用PHPhotoLibrary
这个类.
先说创建相薄:
首先需要定义一个
PHAssetCollection
对象:1private var assetCollection:PHAssetCollection?新增一个创建相薄的方法
createAlbum
:1234567891011121314151617181920212223242526272829303132func createAlbum() {//创建一个FetchOptions,属性选择器let fetchOptions = PHFetchOptions()//指定相薄的名称fetchOptions.predicate = NSPredicate(format: "title = %@", "测试用")//获取相薄的对象let collection = PHAssetCollection.fetchAssetCollectionsWithType(.Album, subtype: .Any, options: fetchOptions)//如果查询出的第一个对象存在,那么就说明相薄已经存在了,直接赋值if let _ = collection.firstObject {assetCollection = collection.firstObject as? PHAssetCollection}else {//否则需要创建一个新的相薄var assetCollectionPlaceholder:PHObjectPlaceholder!//调用performChanges方法来创建相薄PHPhotoLibrary.sharedPhotoLibrary().performChanges({ () -> Void in//根据title来创建一个相薄的请求let createAlbumRequest = PHAssetCollectionChangeRequest.creationRequestForAssetCollectionWithTitle("测试用")//获取出请求中的placeholderassetCollectionPlaceholder = createAlbumRequest.placeholderForCreatedAssetCollection}) { (success, error) -> Void in//创建完成的回调if (!success) {NSLog("Error creating album: \(error)");}else{//如果创建成功.那么就要获取到PHAssetCollection,只有有了这个才能把照片存放到这个相薄中let collectionFetchResult = PHAssetCollection.fetchAssetCollectionsWithLocalIdentifiers([assetCollectionPlaceholder.localIdentifier], options: nil)self.assetCollection = collectionFetchResult.firstObject as? PHAssetCollection}}}}创建完成相薄后,就可以保存照片到相薄中了:
123456789101112131415161718192021222324252627282930313233343536373839404142434445func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {let mediaType = info[UIImagePickerControllerMediaType] as! String//尝试创建相薄createAlbum()if mediaType == kUTTypeImage as String {//图片let image = info[UIImagePickerControllerEditedImage] as! UIImage//使用线程同步dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {//保存到自定义的相薄中PHPhotoLibrary.sharedPhotoLibrary().performChanges({ () -> Void in//根据相片得到保存的请求let assetRequest = PHAssetChangeRequest.creationRequestForAssetFromImage(image)//找到placehodlerlet assetPlaceholder = assetRequest.placeholderForCreatedAsset//创建photosAssetlet photosAsset = PHAsset.fetchAssetsInAssetCollection(self.assetCollection!, options: nil)//实例化 保存事件if let albumChangeRequest = PHAssetCollectionChangeRequest(forAssetCollection: self.assetCollection!, assets: photosAsset) {//执行相薄照片的保存albumChangeRequest.addAssets([assetPlaceholder!])}}, completionHandler: { (success, error) -> Void indispatch_async(dispatch_get_main_queue(), {NSLog("Adding Image to Library -> %@", (success ? "Sucess":"Error!"))//if !success {//表示没有保存成功,尝试保存到系统自带的里面//保存到图库UIImageWriteToSavedPhotosAlbum(image, self,"image:didFinishSavingWithError:contextInfo:", nil)}//保存陈红self.dismissViewControllerAnimated(true, completion: nil)})})})}else {//视频...}}
如此就能保存相片到自定义的相薄中了,其实对相薄还可以有其他的操作,比如列出所有相薄的名字,删除相薄等等.这个具体的参考PHPhotoLibrary
类即可.
总结
本文简单的介绍了一下,如何调用系统自带的相机和相册来进行照片和视频的拍摄.同时也介绍了如何自定义相薄,为以后更高级的拍摄功能做了准备.