iOS开发从相册选择照片或拍照

纵饮孤独 提交于 2020-10-16 12:44:27

一行代码搞定图片选择

//
//  gzhPhotoManager.h
//  图片选择
//
//  Created by 郭志贺 on 2020/5/26.
//  Copyright © 2020 郭志贺. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "ViewController.h"

NS_ASSUME_NONNULL_BEGIN
@protocol gzhPhotoManagerDelegate;
@interface gzhPhotoManager : NSObject

+(instancetype)instance;

/// 选择图片
/// @param controller 当前控制器
/// @param target 代理
/// @param pSize 选择照片尺寸 尺寸传(0,0)不进行裁剪
- (void)selectPhotoWithController:(UIViewController *)controller delegate:(id)target size:(CGSize)pSize;

@end


@protocol gzhPhotoManagerDelegate <NSObject>

- (void)selectedPhotoImage:(UIImage *)image;

@end
NS_ASSUME_NONNULL_END
  1 //
  2 //  gzhPhotoManager.m
  3 //  图片选择
  4 //
  5 //  Created by 郭志贺 on 2020/5/26.
  6 //  Copyright © 2020 郭志贺. All rights reserved.
  7 //
  8 
  9 #import "gzhPhotoManager.h"
 10 #import <MobileCoreServices/MobileCoreServices.h>
 11 #import <Photos/Photos.h>
 12 #import <AssetsLibrary/AssetsLibrary.h>
 13 #import <MetalPerformanceShaders/MetalPerformanceShaders.h>
 14 
 15 @interface gzhPhotoManager () <UINavigationControllerDelegate,UIImagePickerControllerDelegate>
 16 
 17 @property (nonatomic, weak) id<gzhPhotoManagerDelegate> delegate;
 18 @property (nonatomic, assign) CGSize photoSize;
 19 @property (nonatomic, strong) UIImage *image;
 20 @property (nonatomic, weak) UIViewController *controller;
 21 @property (nonatomic, strong) UIImagePickerController *imagePickerController;
 22 
 23 @end
 24 
 25 
 26 @implementation gzhPhotoManager
 27 
 28 + (instancetype)instance {
 29     static gzhPhotoManager * shareInstance = nil;
 30     static dispatch_once_t onceToken;
 31     dispatch_once(&onceToken, ^{
 32         shareInstance = [[gzhPhotoManager alloc]init];
 33     });
 34     return shareInstance;
 35 }
 36 -(void)selectPhotoWithController:(UIViewController *)controller delegate:(id)target size:(CGSize)pSize{
 37     
 38     _controller = controller;
 39     _delegate = target;
 40     _photoSize = pSize;
 41     
 42     UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
 43     [alertVC addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil]];
 44     [alertVC addAction:[UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
 45         
 46         [self cameraCheck:action];
 47     }]];
 48     [alertVC addAction:[UIAlertAction actionWithTitle:@"从手机相册中选择" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
 49        
 50         [self phAuthorizationCheck:action];
 51     }]];
 52     [_controller presentViewController:alertVC animated:YES completion:nil];
 53 }
 54 -(void)cameraCheck:(UIAlertAction *)action{
 55     /*
 56      AVAuthorizationStatusNotDetermined = 0,// 系统还未知是否访问,第一次开启相机时
 57      
 58      AVAuthorizationStatusRestricted, // 受限制的
 59      
 60      AVAuthorizationStatusDenied, //不允许
 61      
 62      AVAuthorizationStatusAuthorized // 允许状态
 63      */
 64     
 65     ALAuthorizationStatus author =[ALAssetsLibrary authorizationStatus];
 66     if (author == AVAuthorizationStatusRestricted || author ==AVAuthorizationStatusDenied) {
 67         [self alertViewWithTitle:@"提示" message:@"如需拍照,请检查拍照功能是否开启,可在:设置->隐私->照相.设置"];
 68     }else if (author == AVAuthorizationStatusAuthorized){
 69         [self selectCamera:action];
 70     }else if (author == AVAuthorizationStatusNotDetermined){
 71         [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
 72             
 73             if (granted) {
 74                 
 75                 //允许访问
 76                 [self selectCamera:action];
 77             }else{
 78                 
 79                 //不允许访问
 80                 [self alertViewWithTitle:@"提示" message:@"如需拍照,请检查拍照功能是否开启,可在:设置->隐私->照相.设置"];
 81             }
 82             
 83         }];
 84     }
 85     
 86     
 87 }
 88 
 89 //判断是否有权限访问相簿
 90 - (void)phAuthorizationCheck:(UIAlertAction *)action{
 91     /*
 92      PHAuthorizationStatusNotDetermined,     用户还没有做出选择
 93      PHAuthorizationStatusDenied,            用户拒绝当前应用访问相册(用户当初点击了"不允许")
 94      PHAuthorizationStatusAuthorized         用户允许当前应用访问相册(用户当初点击了"好")
 95      PHAuthorizationStatusRestricted,        因为家长控制, 导致应用无法方法相册(跟用户的选择没有关系)
 96      */
 97     
 98     // 判断授权状态
 99     PHAuthorizationStatus statu = [PHPhotoLibrary authorizationStatus];
100     if (statu == PHAuthorizationStatusRestricted) {
101         NSLog(@"无法访问相簿--PHAuthorizationStatusRestricted");
102         [self alertViewWithTitle:@"提示" message:@"如需拍照,请检查拍照功能是否开启,可在:设置->隐私->照片.设置"];
103     } else if (statu == PHAuthorizationStatusDenied) {
104         NSLog(@"无法访问相簿--PHAuthorizationStatusDenied");
105         [self alertViewWithTitle:@"提示" message:@"如需拍照,请检查拍照功能是否开启,可在:设置->隐私->照片.设置"];
106     } else if (statu == PHAuthorizationStatusAuthorized) {
107         NSLog(@"可以访问相簿--PHAuthorizationStatusAuthorized");
108         [self selectPhotoLibrary:action];
109     } else if (statu == PHAuthorizationStatusNotDetermined) {
110         // 弹框请求用户授权
111         NSLog(@"第一次访问--PHAuthorizationStatusNotDetermined");
112         [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
113             
114             if (status == PHAuthorizationStatusAuthorized) {
115                 [self selectPhotoLibrary:action];
116             }else{
117                 [self alertViewWithTitle:@"提示" message:@"如需拍照,请检查拍照功能是否开启,可在:设置->隐私->照片.设置"];
118             }
119             
120         }];
121         
122     }
123     
124     
125 }
126 // 拍照
127 - (void)selectCamera:(UIAlertAction *)action {
128     if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
129         dispatch_async(dispatch_get_main_queue(), ^{
130             [self alertViewWithTitle:@"警告" message:@"对不起,您的设备不存在相机"];
131         });
132         
133         return;
134     }
135 
136 
137     if (!_imagePickerController) {
138         _imagePickerController = [UIImagePickerController new];
139         _imagePickerController.delegate = self;
140     }
141     if (_photoSize.width!=0&&_photoSize.height!=0) {
142         _imagePickerController.allowsEditing = YES;
143     }else{
144         _imagePickerController.allowsEditing = NO;
145     }
146 
147     _imagePickerController.mediaTypes = @[(NSString *)kUTTypeImage];
148     _imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
149     _imagePickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
150     [_controller presentViewController:_imagePickerController animated:YES completion:nil];
151 }
152 
153 // 从相册中选择
154 - (void)selectPhotoLibrary:(UIAlertAction *)action {
155     if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
156         dispatch_async(dispatch_get_main_queue(), ^{
157              [self alertViewWithTitle:@"警告" message:@"对不起,您的设备不存在相册"];
158         });
159       
160     }
161     if (!_imagePickerController) {
162         _imagePickerController = [UIImagePickerController new];
163         _imagePickerController.delegate = self;
164     }
165     if (_photoSize.width!=0&&_photoSize.height!=0) {
166         _imagePickerController.allowsEditing = YES;
167     }else{
168         _imagePickerController.allowsEditing = NO;
169     }
170     _imagePickerController.mediaTypes = @[(NSString *)kUTTypeImage,(NSString *)kUTTypeMovie];
171     _imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
172     [_controller presentViewController:_imagePickerController animated:YES completion:nil];
173     
174     
175     
176 }
177 #pragma mark -
178 #pragma mark - UIImagePickerViewController delegate
179 - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
180     
181     NSString * mediaType = [info objectForKey:UIImagePickerControllerMediaType];
182     if ([mediaType isEqualToString:(NSString *)kUTTypeImage]){
183         if (_photoSize.height!=0&&_photoSize.width!=0) {
184             UIImage *image = [self fixOrientation:[info objectForKey:UIImagePickerControllerEditedImage]];
185             self.image = [self scaleImage:image Tosize:self.photoSize];
186             if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
187                 UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
188             }
189         }else{
190             UIImage *image = [self fixOrientation:[info objectForKey:UIImagePickerControllerOriginalImage]];
191             self.image = [self scaleImage:image Tosize:self.photoSize];
192             if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
193                 UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
194             }
195         }
196         [picker dismissViewControllerAnimated:YES completion:^{
197             if (self.delegate && [self.delegate respondsToSelector:@selector(selectedPhotoImage:)]) {
198                 if (self.image) {
199                     [self.delegate selectedPhotoImage:self.image];
200                 } else {
201                     [self alertViewWithTitle:@"你还没选择图片呢" message:nil];
202                 }
203             }
204         }];
205     }
206     
207     
208 }
209 
210 -(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
211     [picker dismissViewControllerAnimated:YES completion:nil];
212 }
213 // 裁剪图片
214 - (UIImage *)scaleImage:(UIImage *)img Tosize:(CGSize)size {
215     
216     CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
217     CGSize imgSize = CGSizeMake(0, 0);
218     if (size.width != 0 && size.height != 0) {
219         imgSize = CGSizeMake(size.width, img.size.height*(size.width/img.size.width));
220     } else {
221         imgSize = CGSizeMake(screenWidth*2, img.size.height*(screenWidth/img.size.width)*2);
222     }
223     // 创建一个bitmap的context
224     // 并把它设置成为当前正在使用的context
225     UIGraphicsBeginImageContext(imgSize);
226     // 绘制改变大小的图片
227     [img drawInRect:CGRectMake(0, 0, imgSize.width, imgSize.height)];
228     // 从当前context中创建一个改变大小后的图片
229     UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
230     // 使当前的context出堆栈
231     UIGraphicsEndImageContext();
232     //返回新的改变大小后的图片
233     return scaledImage;
234 }
235 
236 
237 //修正image方向
238 - (UIImage *)fixOrientation:(UIImage *)aImage {
239     
240 
241     if (aImage.imageOrientation == UIImageOrientationUp)
242         return aImage;
243     
244     CGAffineTransform transform = CGAffineTransformIdentity;
245     
246     switch (aImage.imageOrientation) {
247         case UIImageOrientationDown:
248         case UIImageOrientationDownMirrored:
249             transform = CGAffineTransformTranslate(transform, aImage.size.width, aImage.size.height);
250             transform = CGAffineTransformRotate(transform, M_PI);
251             break;
252             
253         case UIImageOrientationLeft:
254         case UIImageOrientationLeftMirrored:
255             transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
256             transform = CGAffineTransformRotate(transform, M_PI_2);
257             break;
258             
259         case UIImageOrientationRight:
260         case UIImageOrientationRightMirrored:
261             transform = CGAffineTransformTranslate(transform, 0, aImage.size.height);
262             transform = CGAffineTransformRotate(transform, -M_PI_2);
263             break;
264         default:
265             break;
266     }
267     
268     switch (aImage.imageOrientation) {
269         case UIImageOrientationUpMirrored:
270         case UIImageOrientationDownMirrored:
271             transform = CGAffineTransformTranslate(transform, aImage.size.width, 0);
272             transform = CGAffineTransformScale(transform, -1, 1);
273             break;
274             
275         case UIImageOrientationLeftMirrored:
276         case UIImageOrientationRightMirrored:
277             transform = CGAffineTransformTranslate(transform, aImage.size.height, 0);
278             transform = CGAffineTransformScale(transform, -1, 1);
279             break;
280         default:
281             break;
282     }
283 
284     CGContextRef ctx = CGBitmapContextCreate(NULL, aImage.size.width, aImage.size.height,
285                                              CGImageGetBitsPerComponent(aImage.CGImage), 0,
286                                              CGImageGetColorSpace(aImage.CGImage),
287                                              CGImageGetBitmapInfo(aImage.CGImage));
288     CGContextConcatCTM(ctx, transform);
289     switch (aImage.imageOrientation) {
290         case UIImageOrientationLeft:
291         case UIImageOrientationLeftMirrored:
292         case UIImageOrientationRight:
293         case UIImageOrientationRightMirrored:
294             // Grr...
295             CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.height,aImage.size.width), aImage.CGImage);
296             break;
297             
298         default:
299             CGContextDrawImage(ctx, CGRectMake(0,0,aImage.size.width,aImage.size.height), aImage.CGImage);
300             break;
301     }
302     
303     // And now we just create a new UIImage from the drawing context
304     CGImageRef cgimg = CGBitmapContextCreateImage(ctx);
305     UIImage *img = [UIImage imageWithCGImage:cgimg];
306     CGContextRelease(ctx);
307     CGImageRelease(cgimg);
308     return img;
309 }
310 
311 
312 // 提醒
313 - (void)alertViewWithTitle:(NSString *)title message:(NSString *)msg {
314     UIAlertController *alertVC = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert];
315     [alertVC addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]];
316     [_controller presentViewController:alertVC animated:YES completion:nil];
317 }
318 
319 
320 @end

在需要使用的地方遵循<gzhPhotoManagerDelegate>协议

 1 //
 2 //  ViewController.m
 3 //  图片选择
 4 //
 5 //  Created by 郭志贺 on 2020/5/26.
 6 //  Copyright © 2020 郭志贺. All rights reserved.
 7 //
 8 
 9 #import "ViewController.h"
10 #import "gzhPhotoManager.h"
11 
12 /** 屏幕高度 */
13 #define ScreenH [UIScreen mainScreen].bounds.size.height
14 /** 屏幕宽度 */
15 #define ScreenW [UIScreen mainScreen].bounds.size.width
16 
17 @interface ViewController ()<gzhPhotoManagerDelegate>
18 @property(nonatomic,strong)UIImageView * selectImageView;
19 @end
20 
21 @implementation ViewController
22 
23 - (void)viewDidLoad {
24     [super viewDidLoad];
25     // Do any additional setup after loading the view.
26     
27     _selectImageView = [[UIImageView alloc]init];
28     _selectImageView.frame = CGRectMake(0, 0, ScreenW, ScreenH);
29     _selectImageView.contentMode = UIViewContentModeScaleAspectFit;
30     _selectImageView.clipsToBounds = YES;
31     _selectImageView.backgroundColor = [UIColor purpleColor];
32     [self.view addSubview:_selectImageView];
33     
34     _selectImageView.userInteractionEnabled = YES;
35     UITapGestureRecognizer * selectPhotoTapGes = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(selectPhoto:)];
36     [_selectImageView addGestureRecognizer:selectPhotoTapGes];
37     
38 }
39 -(void)selectPhoto:(UITapGestureRecognizer *)taps{
40     //调用
41     [[gzhPhotoManager instance]selectPhotoWithController:self delegate:self size:CGSizeMake(ScreenW, ScreenW)];
42     
43 }
44 -(void)selectedPhotoImage:(UIImage *)image{
45     
46     _selectImageView.image = image;
47     
48     
49 }
50 @end

可直接复制使用,新手见解,如有遗漏或不足敬请告知。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!