當我們需要調(diào)用相機時赫模,通常有兩個方案问拘,一是使用系統(tǒng)定制UI的UIImagePickerController赦抖,二是使用可以自定義UI的AVCaptureSession淘钟。
如果我們不要求自定義UI則可以直接使用UIImagePickerController宦赠,可以節(jié)省時間。
@interface UIImagePickerController : UINavigationController
我們來看一下整個流程:
1.在項目的info.plist中添加相關(guān)使用描述:
<key>NSCameraUsageDescription</key>
<string>這里添加相機權(quán)限描述</string>
<key>NSMicrophoneUsageDescription</key>
<string>這里添加麥克風權(quán)限描述</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>這里添加保存到相冊權(quán)限描述</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>這里添加相冊權(quán)限描述</string>
2.初始化UIImagePickerController
@property (strong,nonatomic) UIImagePickerController* pickController;
//在跳轉(zhuǎn)到相機的方法中
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; //是否提供編輯交互界面 比如說拍完照之后的編輯頁面(縮放,剪裁等)
//使用內(nèi)置編輯控件時米母,圖像選擇器控制器會強制執(zhí)行某些選項勾扭。對于照片,強制執(zhí)行方形裁剪以及最大像素尺寸铁瞒。對于視頻妙色,選擇器強制執(zhí)行最大電影長度和分辨率。如果要讓用戶指定自定義裁剪慧耍,則必須提供自己的編輯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 returnsNO
if the camera is unavailable.
永遠要調(diào)用這個方法來測試設備相機芍碧。永遠不要主觀認為每個設備都有相機煌珊。一個設備即使有攝像頭,在那個攝像頭不可用時泌豆,該方法也會返回NO定庵。
self.pickController.sourceType
// default value is UIImagePickerControllerSourceTypePhotoLibrary.
// 選擇要訪問的源類型
//typedef NS_ENUM(NSInteger, UIImagePickerControllerSourceType) {
// UIImagePickerControllerSourceTypePhotoLibrary, //圖庫
// UIImagePickerControllerSourceTypeCamera, //相機
// UIImagePickerControllerSourceTypeSavedPhotosAlbum //相機膠卷
//}
self.pickController.mediaTypes
//指定媒體類型是什么 照片還是視頻
//默認為 照片
//通過下一行方法可以返回支持的類型
[UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
//查到很多資料都是"kUTTypeMovie","kUTTypeImage"這兩個參數(shù)名稱但是我測試后發(fā)現(xiàn)已經(jīng)變成下面這兩種名稱
//"public.image" 照片
//"public.movie" 視頻
//如果全部支持可以這么設置
self.pickController.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
//單個支持
self.pickController.mediaTypes = @[@"public.image"];
最后設置完代理后,別忘了遵守協(xié)議:
<UINavigationControllerDelegate,UIImagePickerControllerDelegate>
3.實現(xiàn)協(xié)議方法:
// 控制器不會自己dismiss 需要我們手動在相應的地方實現(xiàn)
// 這兩個代理方法只會收到其中一個踪危,取決于用戶的點擊情況
//結(jié)束采集之后 之后怎么處理都在這里寫 通過Infokey取出相應的信息 Infokey可在進入文件中查看
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey, id> *)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.跳轉(zhuǎn)到相機前確認權(quán)限:
AVAuthorizationStatus cameraStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
//相機權(quán)限
// 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];
/* 相冊權(quán)限檢測 需要導入 #import <Photos/Photos.h> 框架
typedef NS_ENUM(NSInteger, PHAuthorizationStatus) {
PHAuthorizationStatusNotDetermined = 0, // 用戶還沒有選擇
PHAuthorizationStatusRestricted, // 客戶端未被授權(quán)訪問敛滋。用戶不能改變狀態(tài),可能是由于家長控制
PHAuthorizationStatusDenied, // 用戶明確拒絕
PHAuthorizationStatusAuthorized // 用戶同意訪問
} PHOTOS_AVAILABLE_IOS_TVOS_OSX(8_0, 10_0, 10_13);
*/
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
//相冊訪問權(quán)限
if (status == PHAuthorizationStatusAuthorized) {
NSLog(@"Authorized");
}else{
NSLog(@"Denied or Restricted");
}
}];
ps:這里有一個坑:
測試手機版本(12.1.4) 7P
點擊拒絕訪問用戶相冊之后還是會進入相冊许布,且下次也可以進入兴革,貌似不需要用戶授權(quán)即可訪問用戶相冊。
把Info.plist中的相冊使用權(quán)限描述刪除之后 且 把相冊權(quán)限檢測方法刪掉 可以直接訪問用戶相冊不報錯。
如果添加了相冊檢測方法則需要在Info.plist文件中添加相冊使用描述杂曲,否則報錯庶艾。
在需要跳轉(zhuǎn)的地方執(zhí)行:
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion;
即可進入到系統(tǒng)定制UI的相機頁面,這時我們可能會發(fā)現(xiàn)為什么界面都是英文的呢?
這樣做:
在Localizations中添加中文源擎勘,然后在target中改成China即可咱揍。
?
5.說下CameraOverLayView
UIImageViewController的這個屬性,可以給其賦值實現(xiàn)自定義相機控制view棚饵。就是說我們自己寫好一個view上面有各種控制按鈕煤裙,將其替代系統(tǒng)的相機控制按鈕(快門鍵,切換前后置噪漾,閃光燈控制等)硼砰。
@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); // 是否顯示系統(tǒng)標準控制UI。默認YES
6.可能會遇到的問題:
如果在設置為如下sourceType時報錯
self.pickController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Source type must be UIImagePickerControllerSourceTypeCamera'
注意:
當我們使用相冊的時候 就無法給這個
self.pickController.showsCameraControls
屬性賦值
解決辦法: 不寫這一行,采用默認值;