Skip to content

Commit

Permalink
Merge branch 'QMUI/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
wanhmr committed Jun 4, 2017
2 parents 203e937 + 24f3d38 commit 4d9a71e
Show file tree
Hide file tree
Showing 100 changed files with 1,909 additions and 575 deletions.
2 changes: 1 addition & 1 deletion QMUIKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "QMUIKit"
s.version = "1.6.0"
s.version = "1.7.1"
s.summary = "致力于提高项目 UI 开发效率的解决方案"
s.description = <<-DESC
QMUI iOS 是一个致力于提高项目 UI 开发效率的解决方案,其设计目的是用于辅助快速搭建一个具备基本设计还原效果的 iOS 项目,同时利用自身提供的丰富控件及兼容处理, 让开发者能专注于业务需求而无需耗费精力在基础代码的设计上。不管是新项目的创建,或是已有项目的维护,均可使开发效率和项目质量得到大幅度提升。
Expand Down
8 changes: 4 additions & 4 deletions QMUIKit/QMUIKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@

#import <UIKit/UIKit.h>

/// QMUIBase
#import "QMUIHelper.h"
#import "QMUICommonDefines.h"
#import "QMUIConfigurationMacros.h"
/// QMUICore
#import "QMUICore.h"

/// QMUIKit
#import "QMUIVisualEffectView.h"
Expand Down Expand Up @@ -91,6 +89,8 @@
#import "QMUIMoreOperationController.h"
#import "QMUIDialogViewController.h"
#import "QMUIOrderedDictionary.h"
#import "QMUIMarqueeLabel.h"
#import "QMUISlider.h"

/// UIMainFrame
#import "QMUISearchController.h"
Expand Down
40 changes: 32 additions & 8 deletions QMUIKit/UIComponents/AssetLibrary/QMUIAsset.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ typedef NS_ENUM(NSUInteger, QMUIAssetDownloadStatus) {
*
* @return 返回请求图片的请求 id
*/
- (NSInteger)requestOriginImageWithCompletion:(void (^)(UIImage *, NSDictionary *))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler;
- (NSInteger)requestOriginImageWithCompletion:(void (^)(UIImage *result, NSDictionary *info))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler;

/**
* 异步请求 Asset 的缩略图,不会产生网络请求
Expand All @@ -83,7 +83,7 @@ typedef NS_ENUM(NSUInteger, QMUIAssetDownloadStatus) {
*
* @return 返回请求图片的请求 id
*/
- (NSInteger)requestThumbnailImageWithSize:(CGSize)size completion:(void (^)(UIImage *, NSDictionary *))completion;
- (NSInteger)requestThumbnailImageWithSize:(CGSize)size completion:(void (^)(UIImage *result, NSDictionary *info))completion;

/**
* 异步请求 Asset 的预览图,可能会有网络请求
Expand All @@ -96,20 +96,42 @@ typedef NS_ENUM(NSUInteger, QMUIAssetDownloadStatus) {
*
* @return 返回请求图片的请求 id
*/
- (NSInteger)requestPreviewImageWithCompletion:(void (^)(UIImage *, NSDictionary *))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler;
- (NSInteger)requestPreviewImageWithCompletion:(void (^)(UIImage *result, NSDictionary *info))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler;

/**
* 异步请求 Live Photo,可能会有网络请求,仅当 assetType 为 QMUIAssetTypeLivePhoto 时有返回值,否则返回 nil
* 异步请求 Live Photo,可能会有网络请求
*
* @param completion 完成请求后调用的 block,参数中包含了请求的 Live Photo 以及相关信息
* @param completion 完成请求后调用的 block,参数中包含了请求的 Live Photo 以及相关信息,若 assetType 不是 QMUIAssetTypeLivePhoto 则为 nil
* @param phProgressHandler 处理请求进度的 handler,不在主线程上执行,在 block 中修改 UI 时注意需要手工放到主线程处理。
*
* @wraning iOS 9.1 以下中并没有 Live Photo,因此返回 nil
* @wraning iOS 9.1 以下中并没有 Live Photo,因此无法获取有效结果
*
* @return 返回请求图片的请求 id
*/
- (NSInteger)requestLivePhotoWithCompletion:(void (^)(PHLivePhoto *, NSDictionary *))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler NS_AVAILABLE_IOS(9_1);
- (NSInteger)requestLivePhotoWithCompletion:(void (^)(PHLivePhoto *livePhoto, NSDictionary *info))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler NS_AVAILABLE_IOS(9_1);

/**
* 异步请求 AVPlayerItem,可能会有网络请求
*
* @param completion 完成请求后调用的 block,参数中包含了请求的 AVPlayerItem 以及相关信息,若 assetType 不是 QMUIAssetTypeVideo 则为 nil
* @param phProgressHandler 处理请求进度的 handler,不在主线程上执行,在 block 中修改 UI 时注意需要手工放到主线程处理。
*
* @wraning iOS 8.0 以下中并没有异步请求 AVPlayerItem 的接口,因此实际上为同步请求,这时 block 中的第二个参数(AVPlayerItem 相关信息)返回的为 nil。
*
* @return 返回请求 AVPlayerItem 的请求 id
*/
- (NSInteger)requestPlayerItemWithCompletion:(void (^)(AVPlayerItem *playerItem, NSDictionary *info))completion withProgressHandler:(PHAssetVideoProgressHandler)phProgressHandler;

/**
* 获取图片的 Data
*
* @param completion 完成请求后调用的 block,参数中包含了请求的图片 Data(若 assetType 不是 QMUIAssetTypeImage 或 QMUIAssetTypeLivePhoto 则为 nil),以及该图片是否为 GIF 的判断值
*/
- (void)requestImageData:(void (^)(NSData *imageData, BOOL isGif))completion;

/**
* 获取图片的 UIImageOrientation 值,仅 assetType 为 QMUIAssetTypeImage 或 QMUIAssetTypeLivePhoto 时有效
*/
- (UIImageOrientation)imageOrientation;

/**
Expand All @@ -125,6 +147,8 @@ typedef NS_ENUM(NSUInteger, QMUIAssetDownloadStatus) {
/**
* 获取 Asset 的体积(数据大小)
*/
- (long long)assetSize;
- (void)assetSize:(void (^)(long long size))completion;

- (NSTimeInterval)duration;

@end
190 changes: 162 additions & 28 deletions QMUIKit/UIComponents/AssetLibrary/QMUIAsset.m
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
#import "QMUIAsset.h"
#import <AssetsLibrary/AssetsLibrary.h>
#import <Photos/Photos.h>
#import "QMUICommonDefines.h"
#import <MobileCoreServices/UTCoreTypes.h>
#import "QMUICore.h"
#import "QMUIAssetsManager.h"
#import "NSString+QMUI.h"

Expand Down Expand Up @@ -158,7 +159,7 @@ - (UIImage *)previewImage {
return resultImage;
}

- (NSInteger)requestOriginImageWithCompletion:(void (^)(UIImage *, NSDictionary *))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler {
- (NSInteger)requestOriginImageWithCompletion:(void (^)(UIImage *result, NSDictionary *info))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler {
if (_usePhotoKit) {
PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc] init];
imageRequestOptions.networkAccessAllowed = YES; // 允许访问网络
Expand All @@ -176,7 +177,7 @@ - (NSInteger)requestOriginImageWithCompletion:(void (^)(UIImage *, NSDictionary
}
}

- (NSInteger)requestThumbnailImageWithSize:(CGSize)size completion:(void (^)(UIImage *, NSDictionary *))completion {
- (NSInteger)requestThumbnailImageWithSize:(CGSize)size completion:(void (^)(UIImage *result, NSDictionary *info))completion {
if (_usePhotoKit) {
PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc] init];
imageRequestOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
Expand All @@ -195,7 +196,7 @@ - (NSInteger)requestThumbnailImageWithSize:(CGSize)size completion:(void (^)(UII
}
}

- (NSInteger)requestPreviewImageWithCompletion:(void (^)(UIImage *, NSDictionary *))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler {
- (NSInteger)requestPreviewImageWithCompletion:(void (^)(UIImage *result, NSDictionary *info))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler {
if (_usePhotoKit) {
PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc] init];
imageRequestOptions.networkAccessAllowed = YES; // 允许访问网络
Expand All @@ -213,7 +214,7 @@ - (NSInteger)requestPreviewImageWithCompletion:(void (^)(UIImage *, NSDictionary
}
}

- (NSInteger)requestLivePhotoWithCompletion:(void (^)(PHLivePhoto *, NSDictionary *))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler {
- (NSInteger)requestLivePhotoWithCompletion:(void (^)(PHLivePhoto *livePhoto, NSDictionary *info))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler {
if (_usePhotoKit && [[PHCachingImageManager class] instancesRespondToSelector:@selector(requestLivePhotoForAsset:targetSize:contentMode:options:resultHandler:)]) {
PHLivePhotoRequestOptions *livePhotoRequestOptions = [[PHLivePhotoRequestOptions alloc] init];
livePhotoRequestOptions.networkAccessAllowed = YES; // 允许访问网络
Expand All @@ -228,17 +229,95 @@ - (NSInteger)requestLivePhotoWithCompletion:(void (^)(PHLivePhoto *, NSDictionar
}
}

- (UIImageOrientation)imageOrientation {
UIImageOrientation orientation;
- (NSInteger)requestPlayerItemWithCompletion:(void (^)(AVPlayerItem *playerItem, NSDictionary *info))completion withProgressHandler:(PHAssetVideoProgressHandler)phProgressHandler {
if (_usePhotoKit && [[PHCachingImageManager class] instancesRespondToSelector:@selector(requestPlayerItemForVideo:options:resultHandler:)]) {
PHVideoRequestOptions *videoRequestOptions = [[PHVideoRequestOptions alloc] init];
videoRequestOptions.networkAccessAllowed = YES; // 允许访问网络
videoRequestOptions.progressHandler = phProgressHandler;
return [[[QMUIAssetsManager sharedInstance] phCachingImageManager] requestPlayerItemForVideo:_phAsset options:videoRequestOptions resultHandler:^(AVPlayerItem * _Nullable playerItem, NSDictionary * _Nullable info) {
if (completion) {
completion(playerItem, info);
}
}];
} else {
NSURL *url = [_alAssetRepresentation url];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];
if (completion) {
completion(playerItem, nil);
}
return 0;
}
}

- (void)requestImageData:(void (^)(NSData *imageData, BOOL isGif))completion {
if (self.assetType != QMUIAssetTypeImage && self.assetType != QMUIAssetTypeLivePhoto) {
if (completion) {
completion(nil, NO);
}
return;
}
if (_usePhotoKit) {
if (!_phAssetInfo) {
// PHAsset 的 UIImageOrientation 需要调用过 requestImageDataForAsset 才能获取
[self requestPhAssetInfo];
[self requestPhAssetInfo:^(NSDictionary *phAssetInfo) {
_phAssetInfo = phAssetInfo;
if (completion) {
NSString *dataUTI = phAssetInfo[@"dataUTI"];
BOOL isGif = [dataUTI isEqualToString:(__bridge NSString *)kUTTypeGIF];
/**
* 这里不在主线程执行,若用户在该 block 中操作 UI 时会产生一些问题,
* 为了避免这种情况,这里该 block 主动放到主线程执行。
*/
dispatch_async(dispatch_get_main_queue(), ^{
completion(phAssetInfo[@"imageData"], isGif);
});
}
}];
} else {
if (completion) {
NSString *dataUTI = _phAssetInfo[@"dataUTI"];
BOOL isGif = [dataUTI isEqualToString:(__bridge NSString *)kUTTypeGIF];
completion(_phAssetInfo[@"imageData"], isGif);
}
}
} else {
if (completion) {
[self assetSize:^(long long size) {
// 获取 NSData 数据
uint8_t *buffer = malloc((size_t)size);
NSError *error;
NSUInteger bytes = [_alAssetRepresentation getBytes:buffer fromOffset:0 length:(NSUInteger)size error:&error];
NSData *imageData = [NSData dataWithBytes:buffer length:bytes];
free(buffer);
// 判断是否为 GIF 图
ALAssetRepresentation *gifRepresentation = [_alAsset representationForUTI: (__bridge NSString *)kUTTypeGIF];
if (gifRepresentation) {
completion(imageData, YES);
} else {
completion(imageData, NO);
}
}];
}
}
}

- (UIImageOrientation)imageOrientation {
UIImageOrientation orientation;
if (self.assetType == QMUIAssetTypeImage || self.assetType == QMUIAssetTypeLivePhoto) {
if (_usePhotoKit) {
if (!_phAssetInfo) {
// PHAsset 的 UIImageOrientation 需要调用过 requestImageDataForAsset 才能获取
[self requestImagePhAssetInfo:^(NSDictionary *phAssetInfo) {
_phAssetInfo = phAssetInfo;
} synchronous:YES];
}
// 从 PhAssetInfo 中获取 UIImageOrientation 对应的字段
orientation = (UIImageOrientation)[_phAssetInfo[@"orientation"] integerValue];
} else {
orientation = (UIImageOrientation)[[_alAsset valueForProperty:@"ALAssetPropertyOrientation"] integerValue];
}
// 从 PhAssetInfo 中获取 UIImageOrientation 对应的字段
orientation = (UIImageOrientation)[_phAssetInfo[@"orientation"] integerValue];
} else {
orientation = (UIImageOrientation)[[_alAsset valueForProperty:@"ALAssetPropertyOrientation"] integerValue];
orientation = UIImageOrientationUp;
}
return orientation;
}
Expand All @@ -258,24 +337,55 @@ - (NSString *)assetIdentity {
return _assetIdentityHash;
}

- (void)requestPhAssetInfo {
if (_phAssetInfo || !_phAsset) {
return;
- (void)requestPhAssetInfo:(void (^)(NSDictionary *))completion {
if (!_phAsset && completion) {
completion(nil);
}

if (self.assetType == QMUIAssetTypeVideo) {
[[[QMUIAssetsManager sharedInstance] phCachingImageManager] requestAVAssetForVideo:_phAsset options:NULL resultHandler:^(AVAsset * _Nullable asset, AVAudioMix * _Nullable audioMix, NSDictionary * _Nullable info) {
if ([asset isKindOfClass:[AVURLAsset class]]) {
NSMutableDictionary *tempInfo = [[NSMutableDictionary alloc] init];
if (info) {
[tempInfo addEntriesFromDictionary:info];
}

AVURLAsset *urlAsset = (AVURLAsset*)asset;
NSNumber *size;
[urlAsset.URL getResourceValue:&size forKey:NSURLFileSizeKey error:nil];
[tempInfo setObject:size forKey:@"size"];
if (completion) {
completion(tempInfo);
}
}
}];
} else {
[self requestImagePhAssetInfo:^(NSDictionary *phAssetInfo) {
if (completion) {
completion(phAssetInfo);
}
} synchronous:NO];
}
}

- (void)requestImagePhAssetInfo:(void (^)(NSDictionary *))completion synchronous:(BOOL)synchronous {
PHImageRequestOptions *imageRequestOptions = [[PHImageRequestOptions alloc] init];
imageRequestOptions.synchronous = YES;
imageRequestOptions.synchronous = synchronous;
imageRequestOptions.networkAccessAllowed = YES;
[[[QMUIAssetsManager sharedInstance] phCachingImageManager] requestImageDataForAsset:_phAsset options:imageRequestOptions resultHandler:^(NSData *imageData, NSString *dataUTI, UIImageOrientation orientation, NSDictionary *info) {
if (info) {
NSMutableDictionary *tempInfo = [[NSMutableDictionary alloc] init];
if (info) {
[tempInfo addEntriesFromDictionary:info];
}
[tempInfo setObject:imageData forKey:@"imageData"];

[tempInfo addEntriesFromDictionary:info];
if (dataUTI) {
[tempInfo setObject:dataUTI forKey:@"dataUTI"];
[tempInfo setObject:dataUTI forKey:@"dataUTI"]; // TODO: kayo 这个字段对应的是不是就是文件的 data?换句话说,要支持 GIF 就要从这里获取 data?
}
[tempInfo setObject:@(orientation) forKey:@"orientation"];
[tempInfo setObject:@(imageData.length) forKey:@"imageSize"];
_phAssetInfo = tempInfo;
[tempInfo setObject:@(imageData.length) forKey:@"size"];
if (completion) {
completion(tempInfo);
}
}
}];
}
Expand All @@ -289,19 +399,43 @@ - (void)updateDownloadStatusWithDownloadResult:(BOOL)succeed {
_downloadStatus = succeed ? QMUIAssetDownloadStatusSucceed : QMUIAssetDownloadStatusFailed;
}

- (long long)assetSize {
long long size;
- (void)assetSize:(void (^)(long long size))completion {
if (_usePhotoKit) {
if (!_phAssetInfo) {
// PHAsset 的 UIImageOrientation 需要调用过 requestImageDataForAsset 才能获取
[self requestPhAssetInfo];
[self requestPhAssetInfo:^(NSDictionary *phAssetInfo) {
_phAssetInfo = phAssetInfo;
if (completion) {
/**
* 这里不在主线程执行,若用户在该 block 中操作 UI 时会产生一些问题,
* 为了避免这种情况,这里该 block 主动放到主线程执行。
*/
dispatch_async(dispatch_get_main_queue(), ^{
completion([phAssetInfo[@"size"] longLongValue]);
});
}
}];
} else {
if (completion) {
completion([_phAssetInfo[@"size"] longLongValue]);
}
}
// 从 PhAssetInfo 中获取 UIImageOrientation 对应的字段
size = [_phAssetInfo[@"imageSize"] longLongValue];
} else {
size = [_alAsset defaultRepresentation].size;
if (completion) {
completion(_alAssetRepresentation.size);
}
}
}

- (NSTimeInterval)duration {
if (self.assetType != QMUIAssetTypeVideo) {
return 0;
}
if (_usePhotoKit) {
return _phAsset.duration;
} else {
return [[_alAsset valueForProperty:ALAssetPropertyDuration] doubleValue];
}
return size;
}

@end
2 changes: 1 addition & 1 deletion QMUIKit/UIComponents/AssetLibrary/QMUIAssetsGroup.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//

#import "QMUIAssetsGroup.h"
#import "QMUICommonDefines.h"
#import "QMUICore.h"
#import "QMUIAsset.h"
#import "QMUIAssetsManager.h"

Expand Down
Loading

0 comments on commit 4d9a71e

Please sign in to comment.