iOS UIImagePickerController轻松调用相机详细介绍

当我们需要调用相机时,通常有两个方案,一是使用系统定制UI的UIImagePickerController,二是使用可以自定义UI的AVCaptureSession。
如果我们不要求自定义UI则可以直接使用UIImagePickerController,可以节省时间。

@interface UIImagePickerController : UINavigationController

我们来看一下整个流程:

1.在项目的info.plist中添加相关使用描述:
    NSCameraUsageDescription
    这里添加相机权限描述

    NSMicrophoneUsageDescription
    这里添加麦克风权限描述

    NSPhotoLibraryAddUsageDescription
    这里添加保存到相册权限描述

    NSPhotoLibraryUsageDescription
    这里添加相册权限描述
2.初始化UIImagePickerController
    @property (strong,nonatomic) UIImagePickerController* pickController;

    //在跳转到相机的方法中
    if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        self.pickController = [[UIImagePickerController alloc]init];
        self.pickController.sourceType = UIImagePickerControllerSourceTypeCamera;
        self.pickController.mediaTypes = @[@"public.image"];
        self.pickController.delegate = self;         //代理设置
        self.pickController.allowsEditing = NO;      //是否提供编辑交互界面 比如说拍完照之后的编辑页面(缩放,剪裁等)
     //使用内置编辑控件时,图像选择器控制器会强制执行某些选项。对于照片,强制执行方形裁剪以及最大像素尺寸。对于视频,选择器强制执行最大电影长度和分辨率。如果要让用户指定自定义裁剪,则必须提供自己的编辑UI。
        self.pickController.showsCameraControls = NO;//是否显示相机控制按钮
        self.pickController.cameraOverlayView = self.cameraOverLayView; //自定义相机控制页面
     //如果不需要自定义控制页面可以省略上面两行
     //设置闪光灯模式
       self.pickController.cameraFlashMode = UIImagePickerControllerCameraFlashModeAuto;
        /*
         typedef NS_ENUM(NSInteger, UIImagePickerControllerCameraFlashMode) {
         UIImagePickerControllerCameraFlashModeOff  = -1,
         UIImagePickerControllerCameraFlashModeAuto = 0,
         UIImagePickerControllerCameraFlashModeOn   = 1
         }
         */
    }else{
        return;
    }

其中:

[UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
//如果设备可用返回YES 否则返回NO

首先使用该方法来测试设备相机的可用性。

Note: Always call the [isSourceTypeAvailable:] class method of the [UIImagePickerController] class and respect its return value. Never assume that a device has a camera. Even if the device has a camera, this method returns NO if the camera is unavailable.
永远要调用这个方法来测试设备相机。永远不要主观认为每个设备都有相机。一个设备即使有摄像头,在那个摄像头不可用时,该方法也会返回NO。

self.pickController.sourceType
// default value is UIImagePickerControllerSourceTypePhotoLibrary.
// 选择要访问的源类型 
//typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
//    UIImagePickerControllerSourceTypePhotoLibrary,     //图库
//    UIImagePickerControllerSourceTypeCamera,           //相机
//    UIImagePickerControllerSourceTypeSavedPhotosAlbum  //相机胶卷
//}
self.pickController.mediaTypes
//指定媒体类型是什么 照片还是视频
//默认为 照片
//通过下一行方法可以返回支持的类型
[UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
//查到很多资料都是"kUTTypeMovie","kUTTypeImage"这两个参数名称但是我测试后发现已经变成下面这两种名称
//"public.image"  照片
//"public.movie"  视频
//如果全部支持可以这么设置
self.pickController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
//单个支持
self.pickController.mediaTypes = @[@"public.image"];

最后设置完代理后,别忘了遵守协议:


3.实现协议方法:
// 控制器不会自己dismiss 需要我们手动在相应的地方实现
// 这两个代理方法只会收到其中一个,取决于用户的点击情况

//结束采集之后 之后怎么处理都在这里写 通过Infokey取出相应的信息  Infokey可在进入文件中查看
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
//查看是视频还是照片  public.image 或 public.movie
NSString * mediaType = [info objectForKey:UIImagePickerControllerMediaType];
    if ([mediaType isEqualToString:@"public.image"]) {//照片
        UIImage* editedImage =(UIImage *)[info objectForKey:
                    UIImagePickerControllerEditedImage]; //取出编辑过的照片
        UIImage* originalImage =(UIImage *)[info objectForKey:
                    UIImagePickerControllerOriginalImage];//取出原生照片
        UIImage* imageToSave = nil;
        if(editedImage){
            imageToSave = editedImage;
        } else {
            imageToSave = originalImage;
        }
    //将新图像(原始图像或已编辑)保存到相机胶卷
        UIImageWriteToSavedPhotosAlbum(imageToSave,nil,nil,nil);
    }
}
    if ([mediaType isEqualToString:@"public.movie"]) {//视频
}
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker; 
//用户点击了取消

4.跳转到相机前确认权限:
AVAuthorizationStatus cameraStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
//相机权限
//     typedef NS_ENUM(NSInteger, AVAuthorizationStatus) {
//     AVAuthorizationStatusNotDetermined = 0,
//     AVAuthorizationStatusRestricted    = 1,
//     AVAuthorizationStatusDenied        = 2,
//     AVAuthorizationStatusAuthorized    = 3,
//     } API_AVAILABLE(macos(10.14), ios(7.0))
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];

  /* 相册权限检测 需要导入 #import  框架
     typedef NS_ENUM(NSInteger, PHAuthorizationStatus) {
     PHAuthorizationStatusNotDetermined = 0, // 用户还没有选择
     PHAuthorizationStatusRestricted,        // 客户端未被授权访问。用户不能改变状态,可能是由于家长控制
     PHAuthorizationStatusDenied,            // 用户明确拒绝
     PHAuthorizationStatusAuthorized         // 用户同意访问
     } PHOTOS_AVAILABLE_IOS_TVOS_OSX(8_0, 10_0, 10_13);
     */
 [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
    //相册访问权限   
     if (status == PHAuthorizationStatusAuthorized) {
            NSLog(@"Authorized");
        }else{
            NSLog(@"Denied or Restricted");
        }
    }];

ps:这里有一个坑:
测试手机版本(12.1.4) 7P
点击拒绝访问用户相册之后还是会进入相册,且下次也可以进入,貌似不需要用户授权即可访问用户相册。
把Info.plist中的相册使用权限描述删除之后 且 把相册权限检测方法删掉 可以直接访问用户相册不报错。
如果添加了相册检测方法则需要在Info.plist文件中添加相册使用描述,否则报错。

在需要跳转的地方执行:

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion;

即可进入到系统定制UI的相机页面,这时我们可能会发现为什么界面都是英文的呢?

这样做:
在Localizations中添加中文源,然后在target中改成China即可。

iOS UIImagePickerController轻松调用相机详细介绍_第1张图片
步骤1

iOS UIImagePickerController轻松调用相机详细介绍_第2张图片
步骤2
5.说下CameraOverLayView

UIImageViewController的这个属性,可以给其赋值实现自定义相机控制view。就是说我们自己写好一个view上面有各种控制按钮,将其替代系统的相机控制按钮(快门键,切换前后置,闪光灯控制等)。

@property(nullable, nonatomic,strong) __kindof UIView *cameraOverlayView  NS_AVAILABLE_IOS(3_1);   // set a view to overlay the preview view.

需要搭配:

@property(nonatomic) BOOL showsCameraControls NS_AVAILABLE_IOS(3_1);   // 是否显示系统标准控制UI。默认YES
6.可能会遇到的问题:

如果在设置为如下sourceType时报错

self.pickController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Source type must be UIImagePickerControllerSourceTypeCamera'

注意:
当我们使用相册的时候 就无法给这个
self.pickController.showsCameraControls
属性赋值
解决办法: 不写这一行,采用默认值;


你可能感兴趣的:(iOS UIImagePickerController轻松调用相机详细介绍)