相机与相册
调用系统相机和相册
添加权限描述:

或者直接在Info.plist中添加配置:
<key>NSPhotoLibraryAddUsageDescription</key>
<string>保存拍照需要该权限</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>测试图库需要权限</string>
<key>NSCameraUsageDescription</key>
<string>测试相机需要权限</string>
图库动态权限请求:
PHAuthorizationStatusNotDetermined:用户从未进行过授权等处理,首次访问相应内容会提示用户进行授权PHAuthorizationStatusRestricted:应用无权访问,且当前用户无法改变这个权限,比如:家长控制PHAuthorizationStatusDenied:用户拒绝访问PHAuthorizationStatusAuthorized:用户已授权,允许访问PHAuthorizationStatusLimited: 用户已授权此应用程序进行有限照片库访问(iOS14新增)
完整示例:
#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <Photos/Photos.h>
@interface ViewController ()<UIImagePickerControllerDelegate,UINavigationControllerDelegate>{
UIImagePickerController *_picker;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info{
[picker dismissViewControllerAnimated:YES completion:nil];
UIImage *image = info[UIImagePickerControllerEditedImage];
// UIImage *image = info[UIImagePickerControllerOriginalImage];
NSLog(@"%@",info);
if ([picker sourceType] == UIImagePickerControllerSourceTypeCamera) {
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}
}
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
NSLog(@"image = %@, error = %@, contextInfo = %@", image, error, contextInfo);
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
[picker dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)onclick:(UIButton *)sender {
switch (sender.tag) {
case 1: // 打开相机
[self openCamera];
break;
case 2: // 打开图库
[self openPhotoLib];
break;
default:
break;
}
}
- (UIImagePickerController*)getPicker{
if(_picker == nil){
_picker = [[UIImagePickerController alloc]init];
_picker.delegate = self;
_picker.allowsEditing = YES;
}
return _picker;
}
-(void)openPhotoLib{
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
if(status == PHAuthorizationStatusNotDetermined){
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status){
NSLog(@"current thread is %@",[NSThread currentThread]);
dispatch_async(dispatch_get_main_queue(), ^{
if(status == PHAuthorizationStatusAuthorized){
[self openImagePicker];
}
});
}];
}else if (status == PHAuthorizationStatusDenied || status == PHAuthorizationStatusRestricted){
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"未获授权,请转到设置页面授权!" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action){
[self dismissViewControllerAnimated:YES completion:nil];
}];
UIAlertAction *setting = [UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){
NSURL *url = [NSURL URLWithString: UIApplicationOpenSettingsURLString];
if([[UIApplication sharedApplication] canOpenURL:url]){
[[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
}
}];
[alert addAction:cancel];
[alert addAction:setting];
[self presentViewController:alert animated:YES completion:nil];
}else{
[self openImagePicker];
}
}
-(void)openImagePicker{
UIImagePickerController *picker = [self getPicker];
// 类型为图库
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController:picker animated:YES completion:nil];
}
-(void)openCamera{
AVAuthorizationStatus status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if(status == AVAuthorizationStatusNotDetermined){
// 首次请求用户授权
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted){
dispatch_async(dispatch_get_main_queue(), ^{
if(granted){
[self startCamera];
}else{
NSLog(@"=========== 拒绝授权 ==========");
}
});
}];
}else if (status == AVAuthorizationStatusDenied){
NSLog(@"=========== 未获得授权 ==========");
}else{
NSLog(@"=========== 已经授权 ==========");
[self startCamera];
}
}
-(void)startCamera{
if([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
UIImagePickerController *picker = [self getPicker];
// 类型为相机
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
// 使用后置摄像头
picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
// 设置为拍照模式
picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
[self presentViewController:picker animated:YES completion:nil];
}
}
@end
保存照片的处理:
UIImageWriteToSavedPhotosAlbum:需要实现(void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo方法creationRequestForAssetFromImage:[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ [PHAssetChangeRequest creationRequestForAssetFromImage:image]; } completionHandler:^(BOOL success, NSError * _Nullable error) { NSLog(@"success = %d, error = %@", success, error); }];
以上两种方式保存照片,都会进行一定程度的压缩,可使用如下方式保存原始照片:
UIImage * imgsave = image;
// 将图片存储到本地沙盒中
NSString * path = [NSHomeDirectory() stringByAppendingString:@"/Documents/test.jpg"];
[UIImagePNGRepresentation(imgsave) writeToFile:path atomically:YES];
// 获取URL,根据URL将图片转存至图库
NSURL *imagePathUrl = [NSURL fileURLWithPath:path];
// 这里要先判断是否获取图库的权限,然后调用以下代码转存到图库
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
[PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:imagePathUrl];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
if (success) NSLog(@"保存成功");
else NSLog(@"保存失败");
}];
注意,启动的照片选择页面可能是英文的,如需显示为中文,则需要在Info.plist中配置一下,将值修改为china:

公众号“编程之路从0到1”