99#import " QMUIAsset.h"
1010#import < AssetsLibrary/AssetsLibrary.h>
1111#import < Photos/Photos.h>
12- #import " QMUICommonDefines.h"
12+ #import < MobileCoreServices/UTCoreTypes.h>
13+ #import " QMUICore.h"
1314#import " QMUIAssetsManager.h"
1415#import " NSString+QMUI.h"
1516
@@ -158,7 +159,7 @@ - (UIImage *)previewImage {
158159 return resultImage;
159160}
160161
161- - (NSInteger )requestOriginImageWithCompletion : (void (^)(UIImage *, NSDictionary *))completion withProgressHandler : (PHAssetImageProgressHandler)phProgressHandler {
162+ - (NSInteger )requestOriginImageWithCompletion : (void (^)(UIImage *result , NSDictionary *info ))completion withProgressHandler : (PHAssetImageProgressHandler)phProgressHandler {
162163 if (_usePhotoKit) {
163164 PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc ] init ];
164165 imageRequestOptions.networkAccessAllowed = YES ; // 允许访问网络
@@ -176,7 +177,7 @@ - (NSInteger)requestOriginImageWithCompletion:(void (^)(UIImage *, NSDictionary
176177 }
177178}
178179
179- - (NSInteger )requestThumbnailImageWithSize : (CGSize)size completion : (void (^)(UIImage *, NSDictionary *))completion {
180+ - (NSInteger )requestThumbnailImageWithSize : (CGSize)size completion : (void (^)(UIImage *result , NSDictionary *info ))completion {
180181 if (_usePhotoKit) {
181182 PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc ] init ];
182183 imageRequestOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
@@ -195,7 +196,7 @@ - (NSInteger)requestThumbnailImageWithSize:(CGSize)size completion:(void (^)(UII
195196 }
196197}
197198
198- - (NSInteger )requestPreviewImageWithCompletion : (void (^)(UIImage *, NSDictionary *))completion withProgressHandler : (PHAssetImageProgressHandler)phProgressHandler {
199+ - (NSInteger )requestPreviewImageWithCompletion : (void (^)(UIImage *result , NSDictionary *info ))completion withProgressHandler : (PHAssetImageProgressHandler)phProgressHandler {
199200 if (_usePhotoKit) {
200201 PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc ] init ];
201202 imageRequestOptions.networkAccessAllowed = YES ; // 允许访问网络
@@ -213,7 +214,7 @@ - (NSInteger)requestPreviewImageWithCompletion:(void (^)(UIImage *, NSDictionary
213214 }
214215}
215216
216- - (NSInteger )requestLivePhotoWithCompletion : (void (^)(PHLivePhoto *, NSDictionary *))completion withProgressHandler : (PHAssetImageProgressHandler)phProgressHandler {
217+ - (NSInteger )requestLivePhotoWithCompletion : (void (^)(PHLivePhoto *livePhoto , NSDictionary *info ))completion withProgressHandler : (PHAssetImageProgressHandler)phProgressHandler {
217218 if (_usePhotoKit && [[PHCachingImageManager class ] instancesRespondToSelector: @selector (requestLivePhotoForAsset:targetSize:contentMode:options:resultHandler: )]) {
218219 PHLivePhotoRequestOptions *livePhotoRequestOptions = [[PHLivePhotoRequestOptions alloc ] init ];
219220 livePhotoRequestOptions.networkAccessAllowed = YES ; // 允许访问网络
@@ -228,17 +229,95 @@ - (NSInteger)requestLivePhotoWithCompletion:(void (^)(PHLivePhoto *, NSDictionar
228229 }
229230}
230231
231- - (UIImageOrientation)imageOrientation {
232- UIImageOrientation orientation;
232+ - (NSInteger )requestPlayerItemWithCompletion : (void (^)(AVPlayerItem *playerItem, NSDictionary *info))completion withProgressHandler : (PHAssetVideoProgressHandler)phProgressHandler {
233+ if (_usePhotoKit && [[PHCachingImageManager class ] instancesRespondToSelector: @selector (requestPlayerItemForVideo:options:resultHandler: )]) {
234+ PHVideoRequestOptions *videoRequestOptions = [[PHVideoRequestOptions alloc ] init ];
235+ videoRequestOptions.networkAccessAllowed = YES ; // 允许访问网络
236+ videoRequestOptions.progressHandler = phProgressHandler;
237+ return [[[QMUIAssetsManager sharedInstance ] phCachingImageManager ] requestPlayerItemForVideo: _phAsset options: videoRequestOptions resultHandler: ^(AVPlayerItem * _Nullable playerItem, NSDictionary * _Nullable info) {
238+ if (completion) {
239+ completion (playerItem, info);
240+ }
241+ }];
242+ } else {
243+ NSURL *url = [_alAssetRepresentation url ];
244+ AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL: url];
245+ if (completion) {
246+ completion (playerItem, nil );
247+ }
248+ return 0 ;
249+ }
250+ }
251+
252+ - (void )requestImageData : (void (^)(NSData *imageData, BOOL isGif))completion {
253+ if (self.assetType != QMUIAssetTypeImage && self.assetType != QMUIAssetTypeLivePhoto) {
254+ if (completion) {
255+ completion (nil , NO );
256+ }
257+ return ;
258+ }
233259 if (_usePhotoKit) {
234260 if (!_phAssetInfo) {
235261 // PHAsset 的 UIImageOrientation 需要调用过 requestImageDataForAsset 才能获取
236- [self requestPhAssetInfo ];
262+ [self requestPhAssetInfo: ^(NSDictionary *phAssetInfo) {
263+ _phAssetInfo = phAssetInfo;
264+ if (completion) {
265+ NSString *dataUTI = phAssetInfo[@" dataUTI" ];
266+ BOOL isGif = [dataUTI isEqualToString: (__bridge NSString *)kUTTypeGIF ];
267+ /* *
268+ * 这里不在主线程执行,若用户在该 block 中操作 UI 时会产生一些问题,
269+ * 为了避免这种情况,这里该 block 主动放到主线程执行。
270+ */
271+ dispatch_async (dispatch_get_main_queue (), ^{
272+ completion (phAssetInfo[@" imageData" ], isGif);
273+ });
274+ }
275+ }];
276+ } else {
277+ if (completion) {
278+ NSString *dataUTI = _phAssetInfo[@" dataUTI" ];
279+ BOOL isGif = [dataUTI isEqualToString: (__bridge NSString *)kUTTypeGIF ];
280+ completion (_phAssetInfo[@" imageData" ], isGif);
281+ }
282+ }
283+ } else {
284+ if (completion) {
285+ [self assetSize: ^(long long size) {
286+ // 获取 NSData 数据
287+ uint8_t *buffer = malloc (size);
288+ NSError *error;
289+ NSUInteger bytes = [_alAssetRepresentation getBytes: buffer fromOffset: 0 length: size error: &error];
290+ NSData *imageData = [NSData dataWithBytes: buffer length: bytes];
291+ free (buffer);
292+ // 判断是否为 GIF 图
293+ ALAssetRepresentation *gifRepresentation = [_alAsset representationForUTI: (__bridge NSString *)kUTTypeGIF ];
294+ if (gifRepresentation) {
295+ completion (imageData, YES );
296+ } else {
297+ completion (imageData, NO );
298+ }
299+ }];
300+ }
301+ }
302+ }
303+
304+ - (UIImageOrientation)imageOrientation {
305+ UIImageOrientation orientation;
306+ if (self.assetType == QMUIAssetTypeImage || self.assetType == QMUIAssetTypeLivePhoto) {
307+ if (_usePhotoKit) {
308+ if (!_phAssetInfo) {
309+ // PHAsset 的 UIImageOrientation 需要调用过 requestImageDataForAsset 才能获取
310+ [self requestImagePhAssetInfo: ^(NSDictionary *phAssetInfo) {
311+ _phAssetInfo = phAssetInfo;
312+ } synchronous: YES ];
313+ }
314+ // 从 PhAssetInfo 中获取 UIImageOrientation 对应的字段
315+ orientation = (UIImageOrientation)[_phAssetInfo[@" orientation" ] integerValue ];
316+ } else {
317+ orientation = (UIImageOrientation)[[_alAsset valueForProperty: @" ALAssetPropertyOrientation" ] integerValue ];
237318 }
238- // 从 PhAssetInfo 中获取 UIImageOrientation 对应的字段
239- orientation = (UIImageOrientation)[_phAssetInfo[@" orientation" ] integerValue ];
240319 } else {
241- orientation = (UIImageOrientation)[[_alAsset valueForProperty: @" ALAssetPropertyOrientation " ] integerValue ] ;
320+ orientation = UIImageOrientationUp ;
242321 }
243322 return orientation;
244323}
@@ -258,24 +337,55 @@ - (NSString *)assetIdentity {
258337 return _assetIdentityHash;
259338}
260339
261- - (void )requestPhAssetInfo {
262- if (_phAssetInfo || !_phAsset) {
263- return ;
340+ - (void )requestPhAssetInfo : (void (^)(NSDictionary *))completion {
341+ if (!_phAsset && completion) {
342+ completion (nil );
343+ }
344+
345+ if (self.assetType == QMUIAssetTypeVideo) {
346+ [[[QMUIAssetsManager sharedInstance ] phCachingImageManager ] requestAVAssetForVideo: _phAsset options: NULL resultHandler: ^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
347+ if ([asset isKindOfClass: [AVURLAsset class ]]) {
348+ NSMutableDictionary *tempInfo = [[NSMutableDictionary alloc ] init ];
349+ if (info) {
350+ [tempInfo addEntriesFromDictionary: info];
351+ }
352+
353+ AVURLAsset *urlAsset = (AVURLAsset*)asset;
354+ NSNumber *size;
355+ [urlAsset.URL getResourceValue: &size forKey: NSURLFileSizeKey error: nil ];
356+ [tempInfo setObject: size forKey: @" size" ];
357+ if (completion) {
358+ completion (tempInfo);
359+ }
360+ }
361+ }];
362+ } else {
363+ [self requestImagePhAssetInfo: ^(NSDictionary *phAssetInfo) {
364+ if (completion) {
365+ completion (phAssetInfo);
366+ }
367+ } synchronous: NO ];
264368 }
369+ }
370+
371+ - (void )requestImagePhAssetInfo : (void (^)(NSDictionary *))completion synchronous : (BOOL )synchronous {
265372 PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc ] init ];
266- imageRequestOptions.synchronous = YES ;
373+ imageRequestOptions.synchronous = synchronous;
374+ imageRequestOptions.networkAccessAllowed = YES ;
267375 [[[QMUIAssetsManager sharedInstance ] phCachingImageManager ] requestImageDataForAsset: _phAsset options: imageRequestOptions resultHandler: ^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
268376 if (info) {
269377 NSMutableDictionary *tempInfo = [[NSMutableDictionary alloc ] init ];
270- if (info) {
271- [tempInfo addEntriesFromDictionary: info];
272- }
378+ [tempInfo setObject: imageData forKey: @" imageData " ];
379+
380+ [tempInfo addEntriesFromDictionary: info];
273381 if (dataUTI) {
274- [tempInfo setObject: dataUTI forKey: @" dataUTI" ];
382+ [tempInfo setObject: dataUTI forKey: @" dataUTI" ]; // TODO: kayo 这个字段对应的是不是就是文件的 data?换句话说,要支持 GIF 就要从这里获取 data?
275383 }
276384 [tempInfo setObject: @(orientation) forKey: @" orientation" ];
277- [tempInfo setObject: @(imageData.length) forKey: @" imageSize" ];
278- _phAssetInfo = tempInfo;
385+ [tempInfo setObject: @(imageData.length) forKey: @" size" ];
386+ if (completion) {
387+ completion (tempInfo);
388+ }
279389 }
280390 }];
281391}
@@ -289,19 +399,43 @@ - (void)updateDownloadStatusWithDownloadResult:(BOOL)succeed {
289399 _downloadStatus = succeed ? QMUIAssetDownloadStatusSucceed : QMUIAssetDownloadStatusFailed;
290400}
291401
292- - (long long )assetSize {
293- long long size;
402+ - (void )assetSize : (void (^)(long long size))completion {
294403 if (_usePhotoKit) {
295404 if (!_phAssetInfo) {
296405 // PHAsset 的 UIImageOrientation 需要调用过 requestImageDataForAsset 才能获取
297- [self requestPhAssetInfo ];
406+ [self requestPhAssetInfo: ^(NSDictionary *phAssetInfo) {
407+ _phAssetInfo = phAssetInfo;
408+ if (completion) {
409+ /* *
410+ * 这里不在主线程执行,若用户在该 block 中操作 UI 时会产生一些问题,
411+ * 为了避免这种情况,这里该 block 主动放到主线程执行。
412+ */
413+ dispatch_async (dispatch_get_main_queue (), ^{
414+ completion ([phAssetInfo[@" size" ] longLongValue ]);
415+ });
416+ }
417+ }];
418+ } else {
419+ if (completion) {
420+ completion ([_phAssetInfo[@" size" ] longLongValue ]);
421+ }
298422 }
299- // 从 PhAssetInfo 中获取 UIImageOrientation 对应的字段
300- size = [_phAssetInfo[@" imageSize" ] longLongValue ];
301423 } else {
302- size = [_alAsset defaultRepresentation ].size ;
424+ if (completion) {
425+ completion (_alAssetRepresentation.size );
426+ }
427+ }
428+ }
429+
430+ - (NSTimeInterval )duration {
431+ if (self.assetType != QMUIAssetTypeVideo) {
432+ return 0 ;
433+ }
434+ if (_usePhotoKit) {
435+ return _phAsset.duration ;
436+ } else {
437+ return [[_alAsset valueForProperty: ALAssetPropertyDuration] doubleValue ];
303438 }
304- return size;
305439}
306440
307441@end
0 commit comments