Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

优化QMUIAsset 获取原始照片的方法(requestOriginImageWithCompletion),解决预览大图时的卡顿 #1056

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions QMUIKit/QMUIComponents/AssetLibrary/QMUIAsset.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ typedef NS_ENUM(NSUInteger, QMUIAssetDownloadStatus) {
*/
- (UIImage *)previewImage;

- (NSInteger)requestOriginalImageWithCompletion:(void (^)(UIImage *image,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed;

/**
* 异步请求 Asset 的原图,包含了系统照片“编辑”功能处理后的效果(剪裁,旋转和滤镜等),可能会有网络请求
*
Expand Down
56 changes: 56 additions & 0 deletions QMUIKit/QMUIComponents/AssetLibrary/QMUIAsset.m
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,62 @@ - (UIImage *)previewImage {
return resultImage;
}

- (NSInteger)requestOriginalImageWithCompletion:(void (^)(UIImage *image,NSDictionary *info,BOOL isDegraded))completion progressHandler:(void (^)(double progress, NSError *error, BOOL *stop, NSDictionary *info))progressHandler networkAccessAllowed:(BOOL)networkAccessAllowed {
CGFloat aspectRatio = _phAsset.pixelWidth / (CGFloat)_phAsset.pixelHeight;
CGFloat pixelWidth = [UIScreen mainScreen].bounds.size.width * ScreenScale;
// 超宽图片
if (aspectRatio > 1.8) {
pixelWidth = pixelWidth * aspectRatio;
}
// 超高图片
if (aspectRatio < 0.2) {
pixelWidth = pixelWidth * 0.5;
}
CGFloat pixelHeight = pixelWidth / aspectRatio;
CGSize imageSize = CGSizeMake(pixelWidth, pixelHeight);

// 修复获取图片时出现的瞬间内存过高问题
// 下面两行代码,来自hsjcom,他的github是:https://github.com/hsjcom 表示感谢
PHImageRequestOptions *option = [[PHImageRequestOptions alloc] init];
option.resizeMode = PHImageRequestOptionsResizeModeFast;
__weak typeof(self) weakSelf = self;
int32_t imageRequestID = [[PHImageManager defaultManager] requestImageForAsset:_phAsset targetSize:imageSize contentMode:PHImageContentModeAspectFill options:option resultHandler:^(UIImage *result, NSDictionary *info) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
BOOL cancelled = [[info objectForKey:PHImageCancelledKey] boolValue];
if (!cancelled && result) {
if (completion) {
completion(result,info,[[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
}
}
// Download image from iCloud / 从iCloud下载图片
if ([info objectForKey:PHImageResultIsInCloudKey] && !result && networkAccessAllowed) {
PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init];
options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) {
dispatch_async(dispatch_get_main_queue(), ^{
if (progressHandler) {
progressHandler(progress, error, stop, info);
}
});
};
options.networkAccessAllowed = YES;
options.resizeMode = PHImageRequestOptionsResizeModeFast;
[[PHImageManager defaultManager] requestImageDataForAsset:strongSelf.phAsset options:options resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
UIImage *resultImage = [UIImage imageWithData:imageData];
if (!resultImage && result) {
resultImage = result;
}
if (completion) {
completion(resultImage,info,NO);
}
}];
}
}];
return imageRequestID;
}

- (NSInteger)requestOriginImageWithCompletion:(void (^)(UIImage *result, NSDictionary<NSString *, id> *info))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler {
PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc] init];
imageRequestOptions.networkAccessAllowed = YES; // 允许访问网络
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,17 +404,43 @@ - (void)requestImageForZoomImageView:(QMUIZoomImageView *)zoomImageView withInde
} else {
imageView.tag = -1;
imageView.image = [imageAsset thumbnailWithSize:CGSizeMake([QMUIImagePickerViewController appearance].minimumImageWidth, [QMUIImagePickerViewController appearance].minimumImageWidth)];
imageAsset.requestID = [imageAsset requestOriginImageWithCompletion:^void(UIImage *result, NSDictionary *info) {
// imageAsset.requestID = [imageAsset requestOriginImageWithCompletion:^void(UIImage *result, NSDictionary *info) {
// // 这里可能因为 imageView 复用,导致前面的请求得到的结果显示到别的 imageView 上,
// // 因此判断如果是新请求(无复用问题)或者是当前的请求才把获得的图片结果展示出来
// dispatch_async(dispatch_get_main_queue(), ^{
// BOOL isNewRequest = (imageView.tag == -1 && imageAsset.requestID == 0);
// BOOL isCurrentRequest = imageView.tag == imageAsset.requestID;
// BOOL loadICloudImageFault = !result || info[PHImageErrorKey];
// if (!loadICloudImageFault && (isNewRequest || isCurrentRequest)) {
// imageView.image = result;
// }
// BOOL downloadSucceed = (result && !info) || (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
// if (downloadSucceed) {
// // 资源资源已经在本地或下载成功
// [imageAsset updateDownloadStatusWithDownloadResult:YES];
// self.downloadStatus = QMUIAssetDownloadStatusSucceed;
// imageView.cloudDownloadStatus = QMUIAssetDownloadStatusSucceed;
// } else if ([info objectForKey:PHImageErrorKey] ) {
// // 下载错误
// [imageAsset updateDownloadStatusWithDownloadResult:NO];
// self.downloadStatus = QMUIAssetDownloadStatusFailed;
// imageView.cloudDownloadStatus = QMUIAssetDownloadStatusFailed;
// }
// });
// } withProgressHandler:phProgressHandler];

//FIXME:优化QMUIAsset 获取原始照片的方法(requestOriginImageWithCompletion),解决预览大图时的卡顿
imageAsset.requestID = [imageAsset requestOriginalImageWithCompletion:^(UIImage *image, NSDictionary *info, BOOL isDegraded) {
// 这里可能因为 imageView 复用,导致前面的请求得到的结果显示到别的 imageView 上,
// 因此判断如果是新请求(无复用问题)或者是当前的请求才把获得的图片结果展示出来
dispatch_async(dispatch_get_main_queue(), ^{
BOOL isNewRequest = (imageView.tag == -1 && imageAsset.requestID == 0);
BOOL isCurrentRequest = imageView.tag == imageAsset.requestID;
BOOL loadICloudImageFault = !result || info[PHImageErrorKey];
BOOL loadICloudImageFault = !image || info[PHImageErrorKey];
if (!loadICloudImageFault && (isNewRequest || isCurrentRequest)) {
imageView.image = result;
imageView.image = image;
}
BOOL downloadSucceed = (result && !info) || (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
BOOL downloadSucceed = (image && !info) || (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
if (downloadSucceed) {
// 资源资源已经在本地或下载成功
[imageAsset updateDownloadStatusWithDownloadResult:YES];
Expand All @@ -427,7 +453,7 @@ - (void)requestImageForZoomImageView:(QMUIZoomImageView *)zoomImageView withInde
imageView.cloudDownloadStatus = QMUIAssetDownloadStatusFailed;
}
});
} withProgressHandler:phProgressHandler];
} progressHandler:phProgressHandler networkAccessAllowed:YES];
imageView.tag = imageAsset.requestID;
}
}
Expand Down
2 changes: 1 addition & 1 deletion QMUIKit/QMUIComponents/QMUIWindowSizeMonitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// Created by ziezheng on 2019/5/27.
//

#import <UIKit/UIkit.h>
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN
Expand Down
2 changes: 1 addition & 1 deletion QMUIKit/UIKitExtensions/UIMenuController+QMUI.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// Created by 陈志宏 on 2019/7/21.
//

#import <UIKit/UIkit.h>
#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

Expand Down