123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- //
- // RQPhotoManager.m
- // RQCommon
- //
- // Created by 张嵘 on 2018/11/26.
- // Copyright © 2018 张嵘. All rights reserved.
- //
- #import "RQPhotoManager.h"
- #import "RQControllerHelper.h"
- #import "TZImageManager.h"
- #import "TZLocationManager.h"
- #import <AssetsLibrary/AssetsLibrary.h>
- /// 位置,use to record the location for photo
- static CLLocation * st_location = nil;
- /// 是否选中了原图
- static BOOL st_isSelectOriginalPhoto = NO;
- /// 允许最大选中照片数
- static CGFloat const RQMaxImagesCount = 8;
- @implementation RQPhotoManager
- #pragma mark - PhotoBrowser
- + (void)showPhotoBrowser:(UIViewController *)viewController photoURLs:(NSArray<NSURL *> *)photoURLsArray initialPageIndex:(NSUInteger)initialPageIndex delegate:(id<IDMPhotoBrowserDelegate>)delegate{
- [self showPhotoBrowser:viewController photoURLs:photoURLsArray initialPageIndex:initialPageIndex animatedFromView:nil scaleImage:nil delegate:delegate];
- }
- + (void)showPhotoBrowser:(UIViewController *)viewController photoURLs:(NSArray<NSURL *> *)photoURLsArray initialPageIndex:(NSUInteger)initialPageIndex animatedFromView:(UIView *)animatedFromView scaleImage:(UIImage *)scaleImage delegate:(id<IDMPhotoBrowserDelegate>)delegate{
- NSArray *photos = [IDMPhoto photosWithURLs:photoURLsArray];
- [self showPhotoBrowser:viewController photos:photos initialPageIndex:initialPageIndex animatedFromView:animatedFromView scaleImage:scaleImage delegate:delegate];
- }
- + (void)showPhotoBrowser:(UIViewController *)viewController photos:(NSArray<IDMPhoto *> *)photosArray initialPageIndex:(NSUInteger)initialPageIndex delegate:(id<IDMPhotoBrowserDelegate>)delegate{
- [self showPhotoBrowser:viewController photos:photosArray initialPageIndex:initialPageIndex animatedFromView:nil scaleImage:nil delegate:delegate];
- }
- + (void)showPhotoBrowser:(UIViewController *)viewController photos:(NSArray<IDMPhoto *> *)photosArray initialPageIndex:(NSUInteger)initialPageIndex animatedFromView:(UIView *)animatedFromView scaleImage:(UIImage *)scaleImage delegate:(id<IDMPhotoBrowserDelegate>)delegate{
- IDMPhotoBrowser *browser = [[IDMPhotoBrowser alloc] initWithPhotos:photosArray animatedFromView:animatedFromView];
- browser.delegate = delegate;
- browser.displayActionButton = NO;
- browser.displayArrowButton = NO;
- browser.displayCounterLabel = YES;
- browser.usePopAnimation = YES;
- browser.scaleImage = scaleImage;
- browser.autoHideInterface = NO;
- browser.forceHideStatusBar = NO;
- browser.disableVerticalSwipe = NO;
- browser.dismissOnTouch = YES;
- browser.displayDoneButton = NO;
- if (initialPageIndex>0) [browser setInitialPageIndex:initialPageIndex];
- if (viewController==nil) viewController = [RQControllerHelper topViewController];
- [viewController presentViewController:browser animated:YES completion:nil];
- }
- #pragma mark - ImagePicker
- + (void)fetchPhotosFromCamera:(UIViewController *)viewController allowCrop:(BOOL)allowCrop completion:(void (^)(UIImage *, id))completion{
- viewController = (viewController == nil)?[RQControllerHelper topViewController]:viewController;
- /// 检查授权
- AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
- if ((authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) && [UIDevice currentDevice].systemVersion.floatValue >= 7.0f) {
- // 无相机权限 做一个友好的提示 ,这个只是针对 iOS8+
- [NSObject rq_showAlertViewWithTitle:@"无法访问你的相机" message:@"请在iPhone的“设置-隐私-相机”选项中,允许轻空访问你相机" confirmTitle:@"设置" cancelTitle:@"取消" confirmAction:^{
- [self accessApplicationSetting:NO];
- !completion?:completion(nil,nil);
- } cancelAction:^{
- !completion?:completion(nil,nil);
- }];
-
- } else if (authStatus == AVAuthorizationStatusNotDetermined) {
- // fix issue 466, 防止用户首次拍照拒绝授权时相机页黑屏
- if (@available(iOS 7.0, *)) {
- [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
- if (granted) {
- dispatch_sync(dispatch_get_main_queue(), ^{
- [self fetchPhotosFromCamera:viewController allowCrop:allowCrop completion:completion];
- });
- }
- }];
- }else {
- [self fetchPhotosFromCamera:viewController allowCrop:allowCrop completion:completion];
- }
- // 拍照之前还需要检查相册权限
- } else if ([self authorizationStatus] == 2) {
- // 已被拒绝,没有相册权限,将无法保存拍的照片 这个只是针对 iOS8+
- [NSObject rq_showAlertViewWithTitle:@"无法访问你的相册" message:@"请在iPhone的“设置-隐私-相册”选项中,允许轻空访问你相册" confirmTitle:@"设置" cancelTitle:@"取消" confirmAction:^{
- [self accessApplicationSetting:YES];
- !completion?:completion(nil,nil);
- } cancelAction:^{
- !completion?:completion(nil,nil);
- }];
- } else if ([self authorizationStatus] == 0) {
- // 未请求过相册权限
- [[TZImageManager manager] requestAuthorizationWithCompletion:^{
- [self fetchPhotosFromCamera:viewController allowCrop:allowCrop completion:completion];
- }];
- } else {
- /// 访问相机
- /// 提前定位
- [[TZLocationManager manager] startLocationWithSuccessBlock:^(NSArray<CLLocation *> *location) {
- if ([location isKindOfClass:[NSArray class]]) {
- st_location = location.firstObject;
- }else {
- st_location = nil;
- }
- } failureBlock:^(NSError *error) {
- st_location = nil;
-
- }];
- if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
- UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;
-
- UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
-
- // set appearance / 改变相册选择页的导航栏外观
- imagePicker.navigationBar.barTintColor = viewController.navigationController.navigationBar.barTintColor;
- imagePicker.navigationBar.tintColor = viewController.navigationController.navigationBar.tintColor;
- UIBarButtonItem *tzBarItem, *BarItem;
- if (@available(iOS 9.0, *)) {
- tzBarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[TZImagePickerController class]]];
- } else {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- //这里写出现警告的代码就能实现去除警告
- tzBarItem = [UIBarButtonItem appearanceWhenContainedIn:[TZImagePickerController class], nil];
- #pragma clang diagnostic pop
- }
- if (@available(iOS 9.0, *)) {
- BarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UIImagePickerController class]]];
- } else {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- //这里写出现警告的代码就能实现去除警告
- BarItem = [UIBarButtonItem appearanceWhenContainedIn:[UIImagePickerController class], nil];
- #pragma clang diagnostic pop
- }
- NSDictionary *titleTextAttributes = [tzBarItem titleTextAttributesForState:UIControlStateNormal];
- [BarItem setTitleTextAttributes:titleTextAttributes forState:UIControlStateNormal];
- imagePicker.sourceType = sourceType;
- // 设置使用手机的前置摄像头。
- imagePicker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
- imagePicker.allowsEditing = allowCrop;
- if (@available(iOS 8.0, *)) {
- imagePicker.modalPresentationStyle = UIModalPresentationOverCurrentContext;
- }
- [viewController presentViewController:imagePicker animated:YES completion:nil];
-
- /// 要监听图片完成的代理
- [imagePicker setBk_didFinishPickingMediaBlock:^(UIImagePickerController *picker, NSDictionary *info) {
- [picker dismissViewControllerAnimated:YES completion:NULL];
- /// 获取到的图片
- UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
- if (!image) image = [info objectForKey:UIImagePickerControllerOriginalImage];
- !completion?:completion(image,nil); /// 回调图片
- /// 保存图片,获取到asset
- // [[TZImageManager manager] savePhotoWithImage:image location:st_location completion:^(PHAsset *asset, NSError *error) {
- // if (!error) {
- // !completion?:completion(image,nil); /// 回调图片
- // } else {
- // !completion?:completion(nil,nil);
- // }
- // }];
- }];
- /// 监听用户取消的代理
- [imagePicker setBk_didCancelBlock:^(UIImagePickerController *picker){
- !completion?:completion(nil,nil);
- if ([picker isKindOfClass:[UIImagePickerController class]]) [picker dismissViewControllerAnimated:YES completion:NULL];
- }];
- } else {
- NSString *title = nil;
- #if TARGET_IPHONE_SIMULATOR
- /// 模拟器
- title = @"模拟器中无法打开照相机,请在真机中使用";
- #else
- /// 真机
- title = @"无法打开你的相机!";
- #endif
- [NSObject rq_showAlertViewWithTitle:title message:nil confirmTitle:@"我知道了"];
- }
- }
- }
- + (void)fetchPhotosFromAlbum:(UIViewController *)viewController maxImagesCount:(NSInteger)maxImagesCount allowCrop:(BOOL)allowCrop selectedAssets:(NSArray *)selecatedAssets completion:(void (^)(NSArray<UIImage *> *, NSArray *, BOOL, NSArray<NSDictionary *> *))completion cancel:(void (^)(void))cancel{
-
- /// show
- if (viewController==nil) viewController = [RQControllerHelper topViewController];
-
- /// imagePicker
- TZImagePickerController *imagePicker = [[TZImagePickerController alloc] initWithMaxImagesCount:(maxImagesCount==0)?[self maxImagesCount]:maxImagesCount columnNumber:[self colunmNumber] delegate:nil];
-
- /// 多选才行
- if (maxImagesCount>1) {
- imagePicker.allowCrop = NO;
- if (selecatedAssets) imagePicker.selectedAssets = [NSMutableArray arrayWithArray:selecatedAssets];
- }else{
- imagePicker.allowCrop = allowCrop;
- }
-
- /// 配置configure
- [self configureImagePicker:imagePicker];
-
- // You can get the photos by block, the same as by delegate.
- // 你可以通过block或者代理,来得到用户选择的照片.
- imagePicker.didFinishPickingPhotosWithInfosHandle = ^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto, NSArray<NSDictionary *> *infos) {
- /// 记录一下选择原图的状态
- [self configureSelectOriginalPhoto:isSelectOriginalPhoto];
-
- /// 回调出去
- !completion?:completion(photos,assets,isSelectOriginalPhoto,infos);
-
- };
-
- // viewController.presentingViewController
- [viewController presentViewController:imagePicker animated:YES completion:nil];
- }
- + (void)previewPhotos:(UIViewController *)viewController maxImagesCount:(NSInteger)maxImagesCount selectedAssets:(NSArray *)selecatedAssets selectedPhotos:(NSMutableArray *)selectedPhotos currentIndex:(NSInteger)currentIndex completion:(void (^)(NSArray<UIImage *> *, NSArray *, BOOL, NSArray<NSDictionary *> *))completion cancel:(void (^)(void))cancel
- {
- /// show
- if (viewController==nil) viewController = [RQControllerHelper topViewController];
- TZImagePickerController *imagePicker = [[TZImagePickerController alloc] initWithSelectedAssets:selecatedAssets.mutableCopy selectedPhotos:selectedPhotos.mutableCopy index:currentIndex];
- imagePicker.maxImagesCount = (maxImagesCount<=0)?[self maxImagesCount]:maxImagesCount;
- imagePicker.allowCrop = NO;
- /// 配置configure
- [self configureImagePicker:imagePicker];
-
- // You can get the photos by block, the same as by delegate.
- // 你可以通过block或者代理,来得到用户选择的照片.
- [imagePicker setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto){
- /// 记录一下选择原图的状态
- [self configureSelectOriginalPhoto:isSelectOriginalPhoto];
- /// 回调出去
- !completion?:completion(photos,assets,isSelectOriginalPhoto,nil);
- }];
-
- // viewController.presentingViewController
- [viewController presentViewController:imagePicker animated:YES completion:nil];
- }
- #pragma mark - ImagePicker Helper
- + (void)configureImagePicker:(TZImagePickerController *)imagePicker
- {
- imagePicker.minImagesCount = 0;
- imagePicker.allowPreview = YES;
- /// 完成按钮可点击
- imagePicker.alwaysEnableDoneBtn = YES;
- /// 这里需要判断一下
- if (imagePicker.allowCrop) {
- imagePicker.allowPickingOriginalPhoto = NO;
- }else{
- imagePicker.allowPickingOriginalPhoto = YES;
- }
-
- /// system defalut configure
- imagePicker.isSelectOriginalPhoto = [self isSelectOriginalPhoto];
-
- /// 不能选择视频
- imagePicker.allowPickingVideo = NO;
- //// 是否需要圆形裁剪
- imagePicker.needCircleCrop = NO;
- /// 圆形裁剪size
- imagePicker.circleCropRadius = (RQ_SCREEN_MIN_LENGTH - 60);
- /// 配置cropView
- imagePicker.cropViewSettingBlock = ^(UIView *cropView) {
- cropView.layer.borderColor = [UIColor whiteColor].CGColor;
- cropView.layer.borderWidth = .5;
- };
- NSInteger left = 0;
- NSInteger widthHeight = RQ_SCREEN_WIDTH - 2 * left;
- NSInteger top = (RQ_SCREEN_HEIGHT - widthHeight) / 2;
- /// 裁剪尺寸
- imagePicker.cropRect = CGRectMake(left, top, widthHeight, widthHeight);
- }
- + (void)fetchOriginalPhotoWithAsset:(id)asset completion:(void (^)(UIImage *, NSDictionary *, BOOL))completion{
- /// 获取原图
- [[TZImageManager manager] getOriginalPhotoWithAsset:asset newCompletion:completion];
- }
- //// 访问设置 isAblum 相册Or相机
- + (void) accessApplicationSetting:(BOOL)isAblum {
- NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
- if (@available(iOS 10.0, *)) {
- if (![[UIApplication sharedApplication] canOpenURL:url]) {
- [NSObject rq_showAlertViewWithTitle:@"十分抱歉" message:@"无法跳转到隐私设置页面,请手动前往设置页面,谢谢" confirmTitle:@"确定"];
- } else {
- [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:nil];
- }
- } else {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- //这里写出现警告的代码就能实现去除警告
- if (![[UIApplication sharedApplication] openURL:url]) {
- [NSObject rq_showAlertViewWithTitle:@"十分抱歉" message:@"无法跳转到隐私设置页面,请手动前往设置页面,谢谢" confirmTitle:@"确定"];
- } else {
- [[UIApplication sharedApplication] openURL:url];
- }
- #pragma clang diagnostic pop
- }
- }
- + (BOOL)isSelectOriginalPhoto{
- return st_isSelectOriginalPhoto;
- }
- + (void)configureSelectOriginalPhoto:(BOOL)selected{
- st_isSelectOriginalPhoto = selected;
- }
- /// 多少列
- + (NSInteger)colunmNumber{
- return (RQ_IS_IPHONE_5||RQ_IS_IPHONE_4_OR_LESS)?3:4;
- }
- /// 允许最大选择
- + (NSInteger)maxImagesCount{
- return RQMaxImagesCount;
- }
- + (NSInteger)authorizationStatus {
- if (@available(iOS 8.0, *)) {
- return [PHPhotoLibrary authorizationStatus];
- } else {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wdeprecated-declarations"
- //这里写出现警告的代码就能实现去除警告
- return [ALAssetsLibrary authorizationStatus];
- #pragma clang diagnostic pop
- }
- }
- @end
|