一行代码搞定图片选择
//
// 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
可直接复制使用,新手见解,如有遗漏或不足敬请告知。
来源:oschina
链接:https://my.oschina.net/u/4288530/blog/4292810