基于 UIImagePickerController 的拓展,分别支持调用相机、相册的功能,其中相机可以设置默认调用前后摄像头;

简单对此进行了封装和实现,其中还有很多点可以继续挖掘和优化,该版本具体 code 如下:

GitHub 链接地址

声明:

/*
相机管理
*/ #import <Foundation/Foundation.h> @protocol YHCameraManagerDelegate <NSObject> /** 事件回调*/
- (void)YHCameraCallBack:(UIImage *)image; @end @interface YHCameraManager : NSObject @property (nonatomic, assign) id <YHCameraManagerDelegate> delegate; /** 单例对象*/
+ (instancetype)shareInstance; /**
调用相机或相册 @param deviceType 摄像头设备类型(默认后置摄像头,前置摄像头需将 deviceType 初始值设置为 @"Front")
@param controller 当前 VC 控件
*/
- (void)openCameraOrPhotoLibraryWithCameraDeviceType:(NSString *)deviceType AndController:(UIViewController *)controller; /**
调用相机拍照 @param deviceType 摄像头设备类型(默认后置摄像头,前置摄像头需将 deviceType 初始值设置为 @"Front")
@param controller 当前 VC 控件
*/
- (void)openCameraWithCameraDeviceType:(NSString *)deviceType AndController:(UIViewController *)controller; /**
调用相机拍摄
@param deviceType deviceType 摄像头设备类型(默认后置摄像头,前置摄像头需将 deviceType 初始值设置为 @"Front")
@param controller controller 当前 VC 控件
*/
- (void)openCameraVideoWithCameraDeviceType:(NSString *)deviceType AndController:(UIViewController *)controller; /**
调用相册
@param controller 当前 VC 控件
*/
- (void)openPhotoLibraryWithController:(UIViewController *)controller; @end

  

实现:

#import "YHCameraManager.h"
#import <AssetsLibrary/AssetsLibrary.h>// 资源库 @interface YHCameraManager () <UIImagePickerControllerDelegate,UINavigationControllerDelegate> @end @implementation YHCameraManager #pragma mark - ****************************** Base
+ (instancetype)shareInstance {
static YHCameraManager *singleton = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
singleton = [[YHCameraManager alloc] init];
}); return singleton;
} #pragma mark - ****************************** Interface methods
/**
调用相机或相册(默认后置摄像头,前置摄像头需将 deviceType 初始值设置为 @"Front")
@param deviceType 摄像头设备类型
@param controller 当前 VC 控件
*/
- (void)openCameraOrPhotoLibraryWithCameraDeviceType:(NSString *)deviceType AndController:(UIViewController *)controller {
UIAlertController *alertCon = [UIAlertController alertControllerWithTitle:nil
message:nil
preferredStyle:UIAlertControllerStyleActionSheet]; kWeakSelf(self);
[alertCon addAction:[UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { [weakself openCameraWithCameraDeviceType:deviceType AndController:controller]; }]];
[alertCon addAction:[UIAlertAction actionWithTitle:@"从相册选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[weakself openPhotoLibraryWithController:controller]; }]]; [alertCon addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { }]]; [controller presentViewController:alertCon animated:YES completion:^{ }];
} /**
调用相机拍照(默认后置摄像头,前置摄像头需将 deviceType 初始值设置为 @"Front")
@param deviceType 摄像头设备类型
@param controller 当前 VC 控件
*/
- (void)openCameraWithCameraDeviceType:(NSString *)deviceType AndController:(UIViewController *)controller {
// 判断是否可以打开照相机
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIImagePickerController *pickerCon = [[UIImagePickerController alloc] init];
pickerCon.delegate = self;
pickerCon.allowsEditing = YES;// 设置拍摄的照片是否允许编辑 // 摄像头
pickerCon.sourceType = UIImagePickerControllerSourceTypeCamera;
pickerCon.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;// 设置拍照类型(拍照 & 摄像)
if ([deviceType isEqualToString:@"Front"]) {// 设置使用手机摄像头类型
pickerCon.cameraDevice = UIImagePickerControllerCameraDeviceFront;// 设置使用手机前置摄像头
}
else {
pickerCon.cameraDevice = UIImagePickerControllerCameraDeviceRear;// 设置使用手机后置摄像头
} [controller presentViewController:pickerCon animated:YES completion:^{
NSLog(@"调用了 --- 摄像头");
}];
}
else {
[MBProgressHUD showCommonHudWithAlertString:@"没有摄像头" afterDelay:2.0 toView:controller.view];
}
} /**
调用相机拍摄 @param deviceType deviceType 摄像头设备类型(默认后置摄像头,前置摄像头需将 deviceType 初始值设置为 @"Front")
@param controller controller 当前 VC 控件
*/
- (void)openCameraVideoWithCameraDeviceType:(NSString *)deviceType AndController:(UIViewController *)controller {
// 判断是否可以打开照相机
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIImagePickerController *pickerCon = [[UIImagePickerController alloc] init];
pickerCon.delegate = self;
pickerCon.allowsEditing = YES;// 设置拍摄的照片是否允许编辑 // 摄像头
pickerCon.sourceType = UIImagePickerControllerSourceTypeCamera;
pickerCon.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];// 将 mediaType 设置为所有支持的媒体类型
pickerCon.cameraCaptureMode = UIImagePickerControllerCameraCaptureModeVideo;// 设置拍照类型(拍照 & 摄像)
pickerCon.videoQuality = UIImagePickerControllerQualityTypeHigh;// 设置拍摄视频的清晰度
if ([deviceType isEqualToString:@"Front"]) {// 设置使用手机摄像头类型
pickerCon.cameraDevice = UIImagePickerControllerCameraDeviceFront;// 设置使用手机前置摄像头
}
else {
pickerCon.cameraDevice = UIImagePickerControllerCameraDeviceRear;// 设置使用手机后置摄像头
} [controller presentViewController:pickerCon animated:YES completion:^{
NSLog(@"调用了 --- 摄像头");
}];
}
else {
[MBProgressHUD showCommonHudWithAlertString:@"没有摄像头" afterDelay:2.0 toView:controller.view];
}
} /**
调用相册 @param controller 当前 VC 控件
*/
- (void)openPhotoLibraryWithController:(UIViewController *)controller {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.allowsEditing = YES;
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.delegate = self; [controller presentViewController:imagePicker animated:YES completion:^{
NSLog(@"调用了 --- 相册");
}];
}
else {
[MBProgressHUD showCommonHudWithAlertString:@"无法打开相册" afterDelay:2.0 toView:controller.view];
}
} #pragma mark - UIImagePickerControllerDelegate
/**
拍照完成回调
@param picker 控件
@param info 数据
*/
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
NSLog(@"UIImagePickerControllerDelegate --- FinishPickingMedia"); // 获取拍摄数据的类型(照片 or 视频)
// NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; if (picker.sourceType == UIImagePickerControllerSourceTypeCamera || picker.sourceType == UIImagePickerControllerSourceTypePhotoLibrary) {// 图片 [mediaType isEqualToString:(NSString *)kUTTypeImage]
UIImage *theImg = nil;
if ([picker allowsEditing]) {// 判断图片是否允许修改
// 获取用户编辑之后的图像
theImg = [info objectForKey:UIImagePickerControllerEditedImage];
}
else {// 获取原图
theImg = [info objectForKey:UIImagePickerControllerOriginalImage];
} // 保存图片至相册中
UIImageWriteToSavedPhotosAlbum(theImg, self, nil, nil); // 图片后续处理相关
if ([self.delegate respondsToSelector:@selector(YHCameraCallBack:)]) {
[self.delegate YHCameraCallBack:theImg];
}
}
else {// 视频
// 获取视频文件 url
NSURL *urlMedia = [info objectForKey:UIImagePickerControllerMediaType];
// 创建 ALAssetsLibrary 对象并将视频保存到媒体库
ALAssetsLibrary *assetsLib = [[ALAssetsLibrary alloc] init];
// 将视频保存至相册
[assetsLib writeVideoAtPathToSavedPhotosAlbum:urlMedia completionBlock:^(NSURL *assetURL, NSError *error) {
if (error) {
NSLog(@"视频拍摄 --- 写入失败:%@", error);
}
else {
NSLog(@"视频拍摄 --- 写入成功");
}
}];
} [picker dismissViewControllerAnimated:YES completion:^{ }];
} /**
拍照页面取消选择的时候,调用该方法
@param picker 当前控件
*/
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:^{ }];
} @end

  

以上便是此次的分析内容,还望大神多多指教!

基于 UIImagePickerController 的拓展封装 - iOS的更多相关文章

  1. 封装ios静态库碰到的一些问题(一)

    封装IOS动态库,碰到的第一个问题,就是资源文件的问题,如果将你的程序封装成为静态库,那么静态库中不会包含资源文件和xib文件,这个时候就需要自己封装bundle文件了,而笔者开发环境默认是xcode ...

  2. Android基于Retrofit2.0 +RxJava 封装的超好用的RetrofitClient工具类(六)

    csdn :码小白 原文地址: http://blog.csdn.net/sk719887916/article/details/51958010 RetrofitClient 基于Retrofit2 ...

  3. 基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil

    基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil,把日常能用到的各种CRUD都进行了简化封装,让普通程序员只需关注业务即可,因为非常简单,故直接贴源代码,大家若需使用可以直 ...

  4. 基于PhoneGap3.4框架的iOS插件的实现

    Phonegap 提供了iOS 设备的基础特性接口来供HTML页面调用,可是这些基础接口不能满足我们的一些特殊需求,所以有时候我们须要开发插件来扩展其功能. 基于PhoneGap3.4框架的iOS插件 ...

  5. 简单的基于promise的ajax封装

    基于promise的ajax封装 //调用方式: /* ajaxPrmomise({ url:, method:, headers:{} }).then(res=>{}) */ ;(functi ...

  6. C#工具类OracleHelper,基于Oracle.ManagedDataAccess.Client封装

    基于Oracle.ManagedDataAccess.Client封装的Oracle工具类OracleHelper,代码如下: using System; using System.Data; usi ...

  7. 基于EFCore3.0+Dapper 封装Repository

    Wei.Repository 基于EFCore3.0+Dapper 封装Repository,实现UnitOfWork,提供基本的CURD操作,可直接注入泛型Repository,也可以继承Repos ...

  8. 基于Ant Design Vue封装一个表单控件

    开源代码 https://github.com/naturefwvue/nf-vue3-ant 有缺点本来是写在最后的,但是博文写的似乎有点太长了,估计大家没时间往下看,于是就把有缺点写在前面了,不喜 ...

  9. iOS开发之网络请求(基于AFNetworking的再封装)

    最近一直很忙也没有什么时间写博客了.放假了休息一下,就写一篇博客来总结一下最近做项目中出现过的问题吧!!! 首先,在项目中我的起到了什么作用,无非就是把美工(UI设计师)给我们的图显示出来,然后再和服 ...

随机推荐

  1. 序列化及json&pickle的使用

    一.序列化 序列化是指把内存里的数据类型转变成字符串.以使其能存储到硬盘或通过网络传输到远程.——硬盘或网络传输时只能接受bytes. Python中用于序列化的两个模块: json:用于字符串和Py ...

  2. 05_Jedis操作Redis

    [工程截图] [String类型操作] package com.higgin.string; import java.util.List; import redis.clients.jedis.Jed ...

  3. Windows8中如何打包和安装一个本地的Metro类型应用(转)

    Windows8中如何打包和安装一个本地的Metro类型应用 (转自:http://software.intel.com/zh-cn/blogs/2012/05/09/windows8metro) 微 ...

  4. php json_encode 中文乱码解决方法

    本文列举3个方法,实现json_encode()后的string显示中文问题. 做接口时不需要,但存log时帮了大忙了. 在贴代码前,必须贴上官方param和return,链接:http://php. ...

  5. java面试题之----数据库事务的四大特性及隔离级别

    本篇讲诉数据库中事务的四大特性(ACID),并且将会详细地说明事务的隔离级别. 如果一个数据库声称支持事务的操作,那么该数据库必须要具备以下四个特性: ⑴ 原子性(Atomicity) 原子性是指事务 ...

  6. C# winform 跨线程修改界面

    我们可以使用invoke和bengininvoke invoke同步执行一个委托 begininvoke异步执行一个委托

  7. #单元测试#以karma+mocha+chai 为测试框架的Vue webpack项目(一)

    目标: 为已有的vue项目搭建 karma+mocha+chai 测试框架 编写组件测试脚本 测试运行通过 抽出共通 一.初始化项目 新建项目文件夹并克隆要测试的已有项目 webAdmin-web 转 ...

  8. IOS 公司标示使用反向域名

    1. 公司标示使用反向域名========================================正向域名 www.baidu.com 用来标示一台网络主机反向域名 cn.itcast.Myd ...

  9. 每天一个linux命令:du 命令

    Linux du命令也是查看使用空间的,但是与df命令不同的是Linux du命令是对文件和目录磁盘使用的空间的查看,还是和df命令有一些区别的. 1.命令格式: du [选项][文件] 2.命令功能 ...

  10. 【洛谷5294】[HNOI2019] 序列(主席树维护单调栈+二分)

    点此看题面 大致题意: 给你一个长度为\(n\)的序列\(A\),每次询问修改一个元素(只对当前询问有效),然后让你找到一个不下降序列\(B\),使得这两个序列相应位置之差的平方和最小,并输出这个最小 ...