iOS8.0以上相冊/相機選擇圖片

前言

在iOS APP開發(fā)中個人設(shè)置中一般會有替換用戶頭像的功能,那么就會需要通過iOS 媒體庫(相機\相冊)來選取圖片。為了簡化操作,和集成方便,一般都會選擇用 UIImagePickerController 來做處理。

我們都知道,iOS系統(tǒng)在7.0以后對調(diào)用相冊\相機設(shè)置很多權(quán)限,每種權(quán)限都有不同的效果,如何處理才能讓用戶體驗更好,也是我們這次主要考慮的方法。

業(yè)務(wù)需求

未命名gif.gif
  • 如果系統(tǒng)自動彈出系統(tǒng)讓用戶授權(quán)的提示框,不再彈出自己業(yè)務(wù)代碼里的提示框

  • 如果系統(tǒng)自動彈出用戶授權(quán)提示框,點擊授權(quán),繼續(xù)執(zhí)行吊起媒體庫控制器的操作

  • 如果用戶未授權(quán),訪問時彈出業(yè)務(wù)提示框,跳轉(zhuǎn)系統(tǒng)設(shè)置中對APP對應(yīng)的設(shè)置

授權(quán)方法說明

相機

   NSString *mediaType = AVMediaTypeVideo;
   AVAuthorizationStatus authStatusVedio = [AVCaptureDevice authorizationStatusForMediaType:mediaType]; 

AVAuthorizationStatus 相機授權(quán)說明

typedef NS_ENUM(NSInteger, AVAuthorizationStatus) {
    AVAuthorizationStatusNotDetermined = 0,  
    AVAuthorizationStatusRestricted    = 1,
    AVAuthorizationStatusDenied        = 2,
    AVAuthorizationStatusAuthorized    = 3,
} NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED;
  • NS_AVAILABLE_IOS(7_0) 表示iOS7.0系統(tǒng)以上均可以使用
  • AVAuthorizationStatusNotDetermined 這個參數(shù)比較特殊,只有用戶在第一次安裝此APP才會返回這個參數(shù),用戶后期更新或者刪除重裝都不會返回這個值,除非設(shè)置中還原。
  • AVAuthorizationStatusRestricted限制使用,可以當(dāng)做不允許使用。
  • AVAuthorizationStatusDenied 禁止使用,可以當(dāng)做不允許使用。
  • AVAuthorizationStatusAuthorized 用戶授權(quán),可以當(dāng)做允許使用。

相冊

 PHAuthorizationStatus authStatusAlbm  = [PHPhotoLibrary authorizationStatus];  

PHAuthorizationStatus 相冊授權(quán)說明

typedef NS_ENUM(NSInteger, PHAuthorizationStatus) {
    PHAuthorizationStatusNotDetermined = 0, // User has not yet made a choice with regards to this application
    PHAuthorizationStatusRestricted,        // This application is not authorized to access photo data.
                                            // The user cannot change this application’s status, possibly due to active restrictions
                                            //   such as parental controls being in place.
    PHAuthorizationStatusDenied,            // User has explicitly denied this application access to photos data.
    PHAuthorizationStatusAuthorized         // User has authorized this application to access photos data.
} PHOTOS_AVAILABLE_IOS_TVOS(8_0, 10_0);

  • PHOTOS_AVAILABLE_IOS_TVOS(8_0, 10_0) 表示iOS8.0系統(tǒng)以上均可以使用
  • PHAuthorizationStatusNotDetermined 這個參數(shù)比較特殊,只有用戶在第一次安裝此APP才會返回這個參數(shù),用戶后期更新或者刪除重裝都不會返回這個值,除非設(shè)置中還原。
  • PHAuthorizationStatusRestricted限制使用,可以當(dāng)做不允許使用。
  • PHAuthorizationStatusDenied 禁止使用,可以當(dāng)做不允許使用。
  • PHAuthorizationStatusAuthorized 用戶授權(quán),可以當(dāng)做允許使用。

源碼

.h文件
#import <Foundation/Foundation.h>

typedef void (^LeePhotoOrAlbumImagePickerBlock)(UIImage *image);

@interface LeePhotoOrAlbumImagePicker : NSObject

// 必須創(chuàng)建一個對象才行,才不會釋放指針
// 必須先在使用該方法的控制器中初始化 創(chuàng)建這個屬性,然后在對象調(diào)用如下方法

/**
 公共方法 選擇圖片后的圖片回掉

 @param controller 使用這個工具的控制器
 @param photoBlock 選擇圖片后的回掉
 */
- (void)getPhotoAlbumOrTakeAPhotoWithController:(UIViewController *)controller photoBlock:(LeePhotoOrAlbumImagePickerBlock)photoBlock;

@end
.m文件

#import "LeePhotoOrAlbumImagePicker.h"
#import <UIKit/UIKit.h>

#import <AssetsLibrary/AssetsLibrary.h>
#import <Photos/PhotosDefines.h>
#import <Photos/PHPhotoLibrary.h>
#import <AVFoundation/AVFoundation.h>
#import <MobileCoreServices/MobileCoreServices.h>


@interface LeePhotoOrAlbumImagePicker ()<UINavigationControllerDelegate, UIImagePickerControllerDelegate>

@property (nonatomic,copy) LeePhotoOrAlbumImagePickerBlock photoBlock;   //-> 回掉
@property (nonatomic,strong) UIImagePickerController *picker; //-> 多媒體選擇控制器
@property (nonatomic,weak) UIViewController  *viewController; //-> 一定是weak 避免循環(huán)引用
@property (nonatomic,assign) NSInteger sourceType;            //-> 媒體來源 (相冊/相機)

@end


@implementation LeePhotoOrAlbumImagePicker

#pragma mark - 初始化
- (instancetype)init{
    if (self = [super init]) {
        
    }
    return self;
}


- (void)getPhotoAlbumOrTakeAPhotoWithController:(UIViewController *)controller photoBlock:(LeePhotoOrAlbumImagePickerBlock)photoBlock{
    self.photoBlock = photoBlock;
    self.viewController = controller;
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
    UIAlertAction *photoAlbumAction = [UIAlertAction actionWithTitle:@"從相冊選擇" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self getAlertActionType:1];
    }];
    UIAlertAction *cemeraAction = [UIAlertAction actionWithTitle:@"拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
        [self getAlertActionType:2];
    }];
    UIAlertAction *cancleAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
        [self getAlertActionType:0];
    }];
    [alertController addAction:photoAlbumAction];
    [alertController addAction:cancleAction];
    // 判斷是否支持拍照
    [self imagePickerControlerIsAvailabelToCamera] ? [alertController addAction:cemeraAction]:nil;
    [self.viewController presentViewController:alertController animated:YES completion:nil];
}



/**
 UIAlertController 點擊事件 確定選擇的媒體來源(相冊/相機)

 @param type 點擊的類型
 */
- (void)getAlertActionType:(NSInteger)type {
    NSInteger sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    if (type == 1) {
        sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    }else if (type ==2){
        sourceType = UIImagePickerControllerSourceTypeCamera;
    }
    [self creatUIImagePickerControllerWithAlertActionType:sourceType];
}



/**
 點擊事件出發(fā)的方法

 @param type 媒體庫來源 (相冊/相機)
 */
- (void)creatUIImagePickerControllerWithAlertActionType:(NSInteger)type {
    self.sourceType = type;
    // 獲取不同媒體類型下的授權(quán)類型
    NSInteger cameragranted = [self AVAuthorizationStatusIsGranted];
    // 如果確定未授權(quán) cameragranted ==0 彈框提示;如果確定已經(jīng)授權(quán) cameragranted == 1;如果第一次觸發(fā)授權(quán) cameragranted == 2,這里不處理
    if (cameragranted == 0) {
        UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"請到設(shè)置-隱私-相機/相冊中打開授權(quán)設(shè)置" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *comfirmAction = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
            // 無權(quán)限 引導(dǎo)去開啟
            NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString];
            if ([[UIApplication sharedApplication]canOpenURL:url]) {
                [[UIApplication sharedApplication]openURL:url];
            }
        }];
        [alertController addAction:comfirmAction];
        [self.viewController presentViewController:alertController animated:YES completion:nil];
    }else if (cameragranted == 1) {
        [self presentPickerViewController];
    }
}


// 判斷硬件是否支持拍照
- (BOOL)imagePickerControlerIsAvailabelToCamera {
    return [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
}

#pragma mark - 照機/相冊 授權(quán)判斷
- (NSInteger)AVAuthorizationStatusIsGranted  {
    kDefineWeakSelf;
    NSString *mediaType = AVMediaTypeVideo;
    AVAuthorizationStatus authStatusVedio = [AVCaptureDevice authorizationStatusForMediaType:mediaType];  // 相機授權(quán)
    PHAuthorizationStatus authStatusAlbm  = [PHPhotoLibrary authorizationStatus];                         // 相冊授權(quán)
    NSInteger authStatus = self.sourceType == UIImagePickerControllerSourceTypePhotoLibrary ? authStatusAlbm:authStatusVedio;
    switch (authStatus) {
        case 0: { //第一次使用,則會彈出是否打開權(quán)限,如果用戶第一次同意授權(quán),直接執(zhí)行再次調(diào)起
            if (self.sourceType == UIImagePickerControllerSourceTypePhotoLibrary) {
                [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
                    if (status == PHAuthorizationStatusAuthorized) { //授權(quán)成功
                        [weakSelf presentPickerViewController];
                    }
                }];
            }else{
                [AVCaptureDevice requestAccessForMediaType : AVMediaTypeVideo completionHandler:^(BOOL granted) {
                    if (granted) { //授權(quán)成功
                        [weakSelf presentPickerViewController];
                    }
                }];
            }
        }
            return 2;   //-> 不提示
        case 1: return 0; //-> 還未授權(quán)
        case 2: return 0; //-> 主動拒絕授權(quán)
        case 3: return 1; //-> 已授權(quán)
        default:return 0;
    }
}


/**
 如果第一次訪問用戶是否是授權(quán),如果用戶同意 直接再次執(zhí)行
 */
-(void)presentPickerViewController{
    self.picker = [[UIImagePickerController alloc] init];
    if (@available(iOS 11.0, *)){
        [[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentAlways];
    }
    self.picker.delegate = self;
    self.picker.allowsEditing = YES;          //-> 是否允許選取的圖片可以裁剪編輯
    self.picker.sourceType = self.sourceType; //-> 媒體來源(相冊/相機)
    [self.viewController presentViewController:self.picker animated:YES completion:nil];
}


#pragma mark - UIImagePickerControllerDelegate
// 點擊完成按鈕的選取圖片的回掉
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
    // 獲取編輯后的圖片
    UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
    // 如果裁剪的圖片不符合標準 就會為空,直接使用原圖
    image == nil    ?  image = [info objectForKey:UIImagePickerControllerOriginalImage] : nil;
    self.photoBlock ?  self.photoBlock(image): nil;
    [picker dismissViewControllerAnimated:YES completion:^{
        // 這個部分代碼 視情況而定
        if (@available(iOS 11.0, *)){
            [[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
        }
    }];
}


-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{
    [picker dismissViewControllerAnimated:YES completion:^{
        // 這個部分代碼 視情況而定
        if (@available(iOS 11.0, *)){
            [[UIScrollView appearance] setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
        }
    }];
}

@end

如何使用

@interface PDMinePostCommentViewController ()

@property (nonatomic,strong) LeePhotoOrAlbumImagePicker *myPicker;

@end

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"意見反饋";
    self.myPicker = [[LeePhotoOrAlbumImagePicker alloc]init];
    [self.myPicker getPhotoAlbumOrTakeAPhotoWithController:self photoBlock:^(UIImage *image) {
        //回掉圖片
    }];
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,048評論 4 61
  • 早上,被工作群的圖片,信息,嚇著,整個胃翻江倒海。 突發(fā)事件,緊急處理。 心慌……無頭緒,也做錯了些事。以前遇到突...
    Alian__閱讀 147評論 0 0
  • 武晨,堅持健身已經(jīng)有十一年之久。因為熱愛健身,做了健身教練;因為熱愛餐飲,創(chuàng)建了自己的餐館。他說自己是一個目標感極...
    美人唐閱讀 453評論 0 1
  • “世界上有2件東西能震撼人們的心靈,一件是我們心中崇高的道德,另一件便是頭頂璀璨的星辰”——康德 首先作為粗...
    放貓抓你閱讀 252評論 0 1

友情鏈接更多精彩內(nèi)容