Skip to content

Commit 7d05bb0

Browse files
committed
Merge commit '5904967359e89b8802e37cfc36c0494cc45d9997'
2 parents cfb568b + 5904967 commit 7d05bb0

101 files changed

Lines changed: 2078 additions & 569 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

QMUI/QMUIKit.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "QMUIKit"
3-
s.version = "1.5.2"
3+
s.version = "1.7.0"
44
s.summary = "致力于提高项目 UI 开发效率的解决方案"
55
s.description = <<-DESC
66
QMUI iOS 是一个致力于提高项目 UI 开发效率的解决方案,其设计目的是用于辅助快速搭建一个具备基本设计还原效果的 iOS 项目,同时利用自身提供的丰富控件及兼容处理, 让开发者能专注于业务需求而无需耗费精力在基础代码的设计上。不管是新项目的创建,或是已有项目的维护,均可使开发效率和项目质量得到大幅度提升。

QMUI/QMUIKit/QMUIKit.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88

99
#import <UIKit/UIKit.h>
1010

11-
/// QMUIBase
12-
#import "QMUIHelper.h"
13-
#import "QMUICommonDefines.h"
14-
#import "QMUIConfigurationMacros.h"
11+
/// QMUICore
12+
#import "QMUICore.h"
1513

1614
/// QMUIKit
1715
#import "QMUIVisualEffectView.h"
@@ -91,6 +89,8 @@
9189
#import "QMUIMoreOperationController.h"
9290
#import "QMUIDialogViewController.h"
9391
#import "QMUIOrderedDictionary.h"
92+
#import "QMUIMarqueeLabel.h"
93+
#import "QMUISlider.h"
9494

9595
/// UIMainFrame
9696
#import "QMUISearchController.h"

QMUI/QMUIKit/UIComponents/AssetLibrary/QMUIAsset.h

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ typedef NS_ENUM(NSUInteger, QMUIAssetDownloadStatus) {
7272
*
7373
* @return 返回请求图片的请求 id
7474
*/
75-
- (NSInteger)requestOriginImageWithCompletion:(void (^)(UIImage *, NSDictionary *))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler;
75+
- (NSInteger)requestOriginImageWithCompletion:(void (^)(UIImage *result, NSDictionary *info))completion withProgressHandler:(PHAssetImageProgressHandler)phProgressHandler;
7676

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

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

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

113+
/**
114+
* 异步请求 AVPlayerItem,可能会有网络请求
115+
*
116+
* @param completion 完成请求后调用的 block,参数中包含了请求的 AVPlayerItem 以及相关信息,若 assetType 不是 QMUIAssetTypeVideo 则为 nil
117+
* @param phProgressHandler 处理请求进度的 handler,不在主线程上执行,在 block 中修改 UI 时注意需要手工放到主线程处理。
118+
*
119+
* @wraning iOS 8.0 以下中并没有异步请求 AVPlayerItem 的接口,因此实际上为同步请求,这时 block 中的第二个参数(AVPlayerItem 相关信息)返回的为 nil。
120+
*
121+
* @return 返回请求 AVPlayerItem 的请求 id
122+
*/
123+
- (NSInteger)requestPlayerItemWithCompletion:(void (^)(AVPlayerItem *playerItem, NSDictionary *info))completion withProgressHandler:(PHAssetVideoProgressHandler)phProgressHandler;
124+
125+
/**
126+
* 获取图片的 Data
127+
*
128+
* @param completion 完成请求后调用的 block,参数中包含了请求的图片 Data(若 assetType 不是 QMUIAssetTypeImage 或 QMUIAssetTypeLivePhoto 则为 nil),以及该图片是否为 GIF 的判断值
129+
*/
130+
- (void)requestImageData:(void (^)(NSData *imageData, BOOL isGif))completion;
131+
132+
/**
133+
* 获取图片的 UIImageOrientation 值,仅 assetType 为 QMUIAssetTypeImage 或 QMUIAssetTypeLivePhoto 时有效
134+
*/
113135
- (UIImageOrientation)imageOrientation;
114136

115137
/**
@@ -125,6 +147,8 @@ typedef NS_ENUM(NSUInteger, QMUIAssetDownloadStatus) {
125147
/**
126148
* 获取 Asset 的体积(数据大小)
127149
*/
128-
- (long long)assetSize;
150+
- (void)assetSize:(void (^)(long long size))completion;
151+
152+
- (NSTimeInterval)duration;
129153

130154
@end

QMUI/QMUIKit/UIComponents/AssetLibrary/QMUIAsset.m

Lines changed: 162 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
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

QMUI/QMUIKit/UIComponents/AssetLibrary/QMUIAssetsGroup.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//
88

99
#import "QMUIAssetsGroup.h"
10-
#import "QMUICommonDefines.h"
10+
#import "QMUICore.h"
1111
#import "QMUIAsset.h"
1212
#import "QMUIAssetsManager.h"
1313

0 commit comments

Comments
 (0)