今天本来想做服务器SSL证书部署的,但是项目发现了一个问题没时间去做了,晚上剩一点点时间就把这个问题记录一下。
当调用系统相机时,在imagePickerController回调时会获取不到Asset。
在didFinishPickingMediaWithInfo里可以直接拿到image对象,一般情况下直接返回image就可以了,根本不需要用到Asset,所以我对Asset也并不是非常了解。
原来的代码里Asset主要用来获取图片的原始Data并返回,由于代码不规范,当Asset为空时就没有回调了,所以才能够发现这个问题。
由于之前用的是ALAssetsLibrary,当时还以为是因为ALAssetsLibrary被废弃而造成的BUG。但是当我将ALAssetsLibrary替换成<Photos/Photos.h>时,这个问题仍然存在。
当我查了一遍度娘后,我猜测:
1、Asset是相当于相册中的图片的资源文件或者能标记对应图片的标识文件。
2、在使用相机拍摄后,当点击“使用照片”按钮时,图片并没有存在相册里,所以就没有生成对应的资源文件。
所以当点击"使用照片",触发了imagePickerController的didFinishPickingMediaWithInfo方法时,无法获取Asset。
经过尝试,只需要在didFinishPickingMediaWithInfo方法中判断Asset,如果Asset为nil则将图片储存,然后再进行一次获取Asset的操作。
#pragma mark - FinishPick -选择照片回调
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info
{
WS(weakSelf);
[picker dismissViewControllerAnimated:YES completion:nil];
UIImage * image = [[UIImage alloc]init];
__block PHAsset *phAsset = [[PHAsset alloc]init];
image = [info valueForKey:UIImagePickerControllerOriginalImage];
phAsset = [self getPHAssetWithInfo:info LocalIdentifier:nil];
if (phAsset == nil) {
[self saveImage_Obj:image completion:^(BOOL success, NSError * _Nullable error, NSString * _Nullable localIdentifier) {
if (success) {
phAsset = [self getPHAssetWithInfo:info LocalIdentifier:localIdentifier];
}
if (!success || phAsset == nil) {
if (weakSelf.getPickImage != nil) {
weakSelf.getPickImage(image,nil);
}
return;
}
[self getImageData:phAsset completion:^(NSData *imageData) {
if (weakSelf.getPickImage != nil) {
weakSelf.getPickImage(image,imageData);
}
}];
}];
}
else
{
[self getImageData:phAsset completion:^(NSData *imageData) {
if (weakSelf.getPickImage != nil) {
weakSelf.getPickImage(image,imageData);
}
}];
}
}
#pragma mark - 获取PHAsset
-(PHAsset *)getPHAssetWithInfo:(NSDictionary<UIImagePickerControllerInfoKey,id> *)info LocalIdentifier:(NSString *)localIdentifier
{
PHAsset *phAsset = [[PHAsset alloc]init];
if (@available(iOS 11.0, *)) {
phAsset = [info valueForKey:UIImagePickerControllerPHAsset];
} else {
// Fallback on earlier versions
NSURL * imageURL = [info valueForKey:UIImagePickerControllerMediaURL];
PHFetchResult *fetchResult = [PHAsset fetchAssetsWithALAssetURLs:@[imageURL] options:nil];
phAsset = fetchResult.firstObject;
}
return phAsset;
}
#pragma mark - 获取图片Data
-(void)getImageData:(PHAsset *)phAsset completion:(nullable void(^)(NSData * imageData))completion
{
PHImageRequestOptions * imageRequest = [[PHImageRequestOptions alloc]init];
imageRequest.version = PHImageRequestOptionsVersionUnadjusted;
[[PHImageManager defaultManager] requestImageDataForAsset:phAsset options:imageRequest resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
if (completion != nil) {
completion(imageData);
}
}];
}
#pragma mark - CancelPick -取消选择回调
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[picker dismissViewControllerAnimated:YES completion:nil];
}
另外今天把这个系统相册、相机的方法都更新了一下,顺便一起发上来吧~
#pragma mark - 使用相册
-(void)UsePhotographAlbum:(GetPickController)getPickController
{
UIImagePickerController *pick = [[UIImagePickerController alloc]init];
pick.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
pick.delegate = self;
[self checkPHAuthorizationStatusWithAllowToUse:^{
if (getPickController != nil) {
getPickController(pick,nil);
}
}];
}
#pragma mark - 使用相机
-(void)UseCamera:(GetPickController)getPickController
{
UIImagePickerController *pick = [[UIImagePickerController alloc]init];
pick.sourceType = UIImagePickerControllerSourceTypeCamera;
pick.delegate = self;
[self checkAVAuthorizationStatusWithAllowToUse:^{
if (getPickController != nil) {
getPickController(pick,nil);
}
}];
}
#pragma mark - 保存视频
- (void)saveVideo:(NSURL *)videoUrl
completion:(nullable void(^)(BOOL success, NSError *__nullable error))completion
{
WS(weakSelf);
[self checkPHAuthorizationStatusWithAllowToUse:^{
[weakSelf saveVideo:videoUrl completion:^(BOOL success, NSError * _Nullable error) {
if (completion != nil) {
completion(success,error);
}
}];
}];
}
#pragma mark - 保存图片
- (void)saveImage:(UIImage *)image
completion:(nullable void(^)(BOOL success, NSError *__nullable error))completion
{
WS(weakSelf);
[self checkPHAuthorizationStatusWithAllowToUse:^{
[weakSelf saveImage_Obj:image completion:^(BOOL success, NSError * _Nullable error, NSString * _Nonnull localIdentifier) {
if (completion != nil) {
completion(success,error);
}
}];
}];
}
#pragma mark - 保存GIF
- (void)saveGIF:(NSString *)gifKey
completion:(nullable void(^)(BOOL success, NSError *__nullable error))completion
{
WS(weakSelf);
[self checkPHAuthorizationStatusWithAllowToUse:^{
NSString * gifPath = [[SDImageCache sharedImageCache] defaultCachePathForKey:gifKey];
NSURL * gifUrl = gifPath.length>0?[NSURL URLWithString:gifPath]:[NSURL URLWithString:gifKey];
[weakSelf saveImage_Obj:gifUrl completion:^(BOOL success, NSError * _Nullable error, NSString * _Nonnull localIdentifier) {
if (completion != nil) {
completion(success,error);
}
}];
}];
}
#pragma mark - 保存图片方法
-(void)saveImage_Obj:(id)image_Obj
completion:(nullable void(^)(BOOL success, NSError *__nullable error, NSString *__nullable localIdentifier))completion
{
// 1. 获取相片库对象
PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
//占位对象
__block PHObjectPlaceholder * placeholder;
// 2. 调用changeBlock
[library performChanges:^{
// 2.1 创建一个相册变动请求
PHAssetCollectionChangeRequest *collectionRequest;
// 2.2 取出指定名称的相册
PHAssetCollection *assetCollection = [self getCurrentPhotoCollectionWithTitle:collectionName];
// 2.3 判断相册是否存在
if (assetCollection) {
// 如果存在就使用当前的相册创建相册请求
collectionRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
} else {
// 如果不存在, 就创建一个新的相册请求
collectionRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:collectionName];
}
// 2.4 根据传入的相片, 创建相片变动请求
PHAssetChangeRequest *assetRequest;
if ([image_Obj isKindOfClass:[UIImage class]]) {
//如果是图片类型
assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:(UIImage *)image_Obj];
}
else if ([image_Obj isKindOfClass:[NSURL class]])
{
//如果是URL类型
assetRequest = [PHAssetChangeRequest creationRequestForAssetFromImageAtFileURL:(NSURL *)image_Obj];
}
else
{
completion(NO,nil,nil);
return;
}
// 2.4 创建一个占位对象
placeholder = [assetRequest placeholderForCreatedAsset];
// 2.5 将占位对象添加到相册请求中
[collectionRequest insertAssets:@[placeholder] atIndexes:[NSIndexSet indexSetWithIndex:0]];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
// 3. 回调
if (completion != nil) {
completion(success,error,placeholder.localIdentifier);
}
}];
}
#pragma mark - 保存视频方法
-(void)saveVideoWithURL:(NSURL *)video_Url
completion:(nullable void(^)(BOOL success, NSError *__nullable error))completion
{
// 1. 获取相片库对象
PHPhotoLibrary *library = [PHPhotoLibrary sharedPhotoLibrary];
// 2. 调用changeBlock
[library performChanges:^{
// 2.1 创建一个相册变动请求
PHAssetCollectionChangeRequest *collectionRequest;
// 2.2 取出指定名称的相册
PHAssetCollection *assetCollection = [self getCurrentPhotoCollectionWithTitle:collectionName];
// 2.3 判断相册是否存在
if (assetCollection) {
// 如果存在就使用当前的相册创建相册请求
collectionRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
} else {
// 如果不存在, 就创建一个新的相册请求
collectionRequest = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:collectionName];
}
// 2.4 根据传入的相片, 创建相片变动请求
PHAssetChangeRequest *assetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:video_Url];
// 2.4 创建一个占位对象
PHObjectPlaceholder *placeholder = [assetRequest placeholderForCreatedAsset];
// 2.5 将占位对象添加到相册请求中
[collectionRequest insertAssets:@[placeholder] atIndexes:[NSIndexSet indexSetWithIndex:0]];
} completionHandler:^(BOOL success, NSError * _Nullable error) {
// 3. 回调
if (completion != nil) {
completion(success,error);
}
}];
}
#pragma mark - 获取相册名称
-(PHAssetCollection *)getCurrentPhotoCollectionWithTitle:(NSString *)collectionName {
// 1. 创建搜索集合
PHFetchResult *result = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
// 2. 遍历搜索集合并取出对应的相册
for (PHAssetCollection *assetCollection in result) {
if ([assetCollection.localizedTitle containsString:collectionName]) {
return assetCollection;
}
}
return nil;
}
#pragma mark - 检查相册权限
-(void)checkPHAuthorizationStatusWithAllowToUse:(nullable void(^)(void))allowToUse
{
// 1. 获取当前App的相册授权状态
PHAuthorizationStatus authorizationStatus = [PHPhotoLibrary authorizationStatus];
// 2. 判断授权状态
if (authorizationStatus == PHAuthorizationStatusAuthorized && allowToUse != nil) {
allowToUse();
} else if (authorizationStatus == PHAuthorizationStatusNotDetermined) { // 如果没决定, 弹出指示框, 让用户选择
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
// 如果用户选择授权, 则保存图片
if (status == PHAuthorizationStatusAuthorized && allowToUse != nil) {
allowToUse();
}
}];
} else {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"请到设置->隐私->照片中开启【华世界商圈】的对应权限,以便于我们能够存取您的图像信息。" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * OK_Action = [UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:^(BOOL success)
{
}];
} else {
//iOS10以前,使用旧API
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
}];
[alertController addAction:OK_Action];
UIAlertAction * Cancel_Action = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
[[AppDelegate lastWindow].viewController.navigationController popViewControllerAnimated:YES];
}];
[alertController addAction:Cancel_Action];
[[AppDelegate lastWindow].rootViewController presentViewController:alertController animated:YES completion:nil];
}
}
#pragma mark - 检查相机权限
-(void)checkAVAuthorizationStatusWithAllowToUse:(nullable void(^)(void))allowToUse
{
//判断是否有相机权限
AVAuthorizationStatus authorizationStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];//读取设备授权状态
if (authorizationStatus == AVAuthorizationStatusAuthorized && allowToUse != nil) {
allowToUse();
}
else if(authorizationStatus == AVAuthorizationStatusNotDetermined){
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (granted == YES && allowToUse != nil) {
allowToUse();
}
}];
} else {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"请到设置->隐私->相机中开启【华世界商圈】的使用权限,以便于我们能够使用您的相机进行拍摄或扫描。" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * OK_Action = [UIAlertAction actionWithTitle:@"设置" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
if (@available(iOS 10.0, *)) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString] options:@{} completionHandler:^(BOOL success)
{
}];
} else {
//iOS10以前,使用旧API
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}
}];
[alertController addAction:OK_Action];
UIAlertAction * Cancel_Action = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
[[AppDelegate lastWindow].viewController.navigationController popViewControllerAnimated:YES];
}];
[alertController addAction:Cancel_Action];
[[AppDelegate lastWindow].rootViewController presentViewController:alertController animated:YES completion:nil];
}
}
网友评论