diff --git a/QMUIKit/QMUIComponents/AssetLibrary/QMUIAsset.h b/QMUIKit/QMUIComponents/AssetLibrary/QMUIAsset.h index d5feb500..b8e1f9bd 100644 --- a/QMUIKit/QMUIComponents/AssetLibrary/QMUIAsset.h +++ b/QMUIKit/QMUIComponents/AssetLibrary/QMUIAsset.h @@ -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 的原图,包含了系统照片“编辑”功能处理后的效果(剪裁,旋转和滤镜等),可能会有网络请求 * diff --git a/QMUIKit/QMUIComponents/AssetLibrary/QMUIAsset.m b/QMUIKit/QMUIComponents/AssetLibrary/QMUIAsset.m index c1f7500a..fdadd737 100644 --- a/QMUIKit/QMUIComponents/AssetLibrary/QMUIAsset.m +++ b/QMUIKit/QMUIComponents/AssetLibrary/QMUIAsset.m @@ -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 *info))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler { PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc] init]; imageRequestOptions.networkAccessAllowed = YES; // 允许访问网络 diff --git a/QMUIKit/QMUIComponents/ImagePickerLibrary/QMUIImagePickerPreviewViewController.m b/QMUIKit/QMUIComponents/ImagePickerLibrary/QMUIImagePickerPreviewViewController.m index 3df99cb7..0b7ce964 100644 --- a/QMUIKit/QMUIComponents/ImagePickerLibrary/QMUIImagePickerPreviewViewController.m +++ b/QMUIKit/QMUIComponents/ImagePickerLibrary/QMUIImagePickerPreviewViewController.m @@ -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]; @@ -427,7 +453,7 @@ - (void)requestImageForZoomImageView:(QMUIZoomImageView *)zoomImageView withInde imageView.cloudDownloadStatus = QMUIAssetDownloadStatusFailed; } }); - } withProgressHandler:phProgressHandler]; + } progressHandler:phProgressHandler networkAccessAllowed:YES]; imageView.tag = imageAsset.requestID; } } diff --git a/QMUIKit/QMUIComponents/QMUIWindowSizeMonitor.h b/QMUIKit/QMUIComponents/QMUIWindowSizeMonitor.h index 83911a34..760ab805 100644 --- a/QMUIKit/QMUIComponents/QMUIWindowSizeMonitor.h +++ b/QMUIKit/QMUIComponents/QMUIWindowSizeMonitor.h @@ -12,7 +12,7 @@ // Created by ziezheng on 2019/5/27. // -#import +#import #import NS_ASSUME_NONNULL_BEGIN diff --git a/QMUIKit/UIKitExtensions/UIMenuController+QMUI.h b/QMUIKit/UIKitExtensions/UIMenuController+QMUI.h index 129d6b3d..1960c185 100644 --- a/QMUIKit/UIKitExtensions/UIMenuController+QMUI.h +++ b/QMUIKit/UIKitExtensions/UIMenuController+QMUI.h @@ -12,7 +12,7 @@ // Created by 陈志宏 on 2019/7/21. // -#import +#import NS_ASSUME_NONNULL_BEGIN