XG_AssetPickerManager.m 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. //
  2. // XG_AssetPickerManager.m
  3. // MyApp
  4. //
  5. // Created by huxinguang on 2018/9/26.
  6. // Copyright © 2018年 huxinguang. All rights reserved.
  7. //
  8. #import "XG_AssetPickerManager.h"
  9. #import "XG_AssetModel.h"
  10. #import "XG_AlbumModel.h"
  11. @interface XG_AssetPickerManager ()
  12. @end
  13. @implementation XG_AssetPickerManager
  14. + (instancetype)manager {
  15. static XG_AssetPickerManager *manager;
  16. static dispatch_once_t onceToken;
  17. dispatch_once(&onceToken, ^{
  18. manager = [[self alloc] init];
  19. });
  20. return manager;
  21. }
  22. -(PHFetchResult<PHAssetCollection *> *)smartAlbums{
  23. if (!_smartAlbums) _smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
  24. return _smartAlbums;
  25. }
  26. - (PHFetchResult<PHCollection *> *)userCollections{
  27. if (!_userCollections) _userCollections = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil];
  28. return _userCollections;
  29. }
  30. - (void)handleAuthorizationWithCompletion:(void (^)(XG_AuthorizationStatus aStatus))completion{
  31. [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
  32. dispatch_async(dispatch_get_main_queue(), ^{
  33. switch (status) {
  34. case PHAuthorizationStatusNotDetermined:{
  35. completion(XG_AuthorizationStatusNotDetermined);
  36. }
  37. break;
  38. case PHAuthorizationStatusRestricted:{
  39. completion(XG_AuthorizationStatusRestricted);
  40. }
  41. break;
  42. case PHAuthorizationStatusDenied:{
  43. completion(XG_AuthorizationStatusDenied);
  44. }
  45. break;
  46. case PHAuthorizationStatusAuthorized:{
  47. completion(XG_AuthorizationStatusAuthorized);
  48. }
  49. break;
  50. default:
  51. break;
  52. }
  53. });
  54. }];
  55. }
  56. #pragma mark - Get Albums
  57. - (void)getAllAlbums:(BOOL)videoPickable completion:(void (^)(NSArray<XG_AlbumModel *> *))completion{
  58. NSMutableArray *albumArr = [NSMutableArray array];
  59. PHFetchOptions *option = [[PHFetchOptions alloc] init];
  60. if (!videoPickable) option.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
  61. option.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]];
  62. // smartAlbums
  63. [self.smartAlbums enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  64. //不同相册的同一张照片,所对应的PHAsset实例的localIdentifier是一样的,但对应的PHAsset实例并不是同一个
  65. PHFetchResult<PHAsset *> *fetchResult = [PHAsset fetchAssetsInAssetCollection:obj options:option];
  66. if (fetchResult.count > 0) {
  67. //把“相机胶卷”放在第一位
  68. //Project中如果添加了Chinese(simplified),那么在真机(语言为中文)运行时,localizedTitle就是中文
  69. if ([obj.localizedTitle isEqualToString:@"最近项目"] || [obj.localizedTitle isEqualToString:@"Recents"]) {
  70. [albumArr insertObject:[self modelWithResult:fetchResult name:obj.localizedTitle videoPickable:videoPickable] atIndex:0];
  71. }else{
  72. [albumArr addObject:[self modelWithResult:fetchResult name:obj.localizedTitle videoPickable:videoPickable]];
  73. }
  74. }
  75. }];
  76. // userCollections
  77. [self.userCollections enumerateObjectsUsingBlock:^(PHCollection * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  78. PHAssetCollection *collection = (PHAssetCollection *)obj;
  79. PHFetchResult<PHAsset *> *fetchResult = [PHAsset fetchAssetsInAssetCollection:collection options:option];
  80. if (fetchResult.count > 0) {
  81. [albumArr addObject:[self modelWithResult:fetchResult name:obj.localizedTitle videoPickable:videoPickable]];
  82. }
  83. }];
  84. if (completion) completion(albumArr);
  85. }
  86. #pragma mark - Get Photo
  87. - (void)getPhotoWithAsset:(PHAsset *)asset completion:(void (^)(id, NSDictionary *))completion {
  88. if (@available(iOS 11.0, *)) {
  89. if (asset.playbackStyle == PHAssetPlaybackStyleImageAnimated) {
  90. [self getDataWithAsset:asset completion:completion];
  91. return;
  92. }
  93. }
  94. [self getPhotoWithAsset:asset photoWidth:[UIScreen mainScreen].bounds.size.width completion:completion];
  95. }
  96. - (void)getDataWithAsset:(PHAsset *)asset completion:(void (^)(id, NSDictionary *))completion{
  97. //动图(Aninated)
  98. [[PHImageManager defaultManager] requestImageDataForAsset:asset options:nil resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, UIImageOrientation orientation, NSDictionary * _Nullable info) {
  99. if (completion) completion(imageData,info);
  100. }];
  101. }
  102. - (void)getPhotoWithAsset:(PHAsset *)asset photoWidth:(CGFloat)photoWidth completion:(void (^)(UIImage *, NSDictionary *))completion {
  103. CGFloat aspectRatio = asset.pixelWidth / (CGFloat)asset.pixelHeight;
  104. CGFloat multiple = [UIScreen mainScreen].scale;
  105. CGFloat pixelWidth = photoWidth * multiple;
  106. CGFloat pixelHeight = pixelWidth / aspectRatio;
  107. [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:CGSizeMake(pixelWidth, pixelHeight) contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
  108. BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
  109. if (downloadFinined) {
  110. if (completion) completion(result,info);
  111. }
  112. }];
  113. }
  114. - (void)getPhotoWithAsset1:(PHAsset *)asset completion:(void (^)(UIImage *, NSDictionary *))completion {
  115. CGFloat aspectRatio = asset.pixelWidth / (CGFloat)asset.pixelHeight;
  116. CGFloat pixelWidth = asset.pixelWidth;
  117. CGFloat pixelHeight = asset.pixelHeight;
  118. [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:CGSizeMake(pixelWidth, pixelHeight) contentMode:PHImageContentModeAspectFit options:nil resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) {
  119. BOOL downloadFinined = (![[info objectForKey:PHImageCancelledKey] boolValue] && ![info objectForKey:PHImageErrorKey] && ![[info objectForKey:PHImageResultIsDegradedKey] boolValue]);
  120. if (downloadFinined) {
  121. if (completion) completion(result,info);
  122. }
  123. }];
  124. }
  125. - (void)getPostImageWithAlbumModel:(XG_AlbumModel *)model completion:(void (^)(UIImage *))completion {
  126. [self getPhotoWithAsset:[model.result firstObject] photoWidth:60 completion:^(UIImage *photo, NSDictionary *info) {
  127. if (completion) completion(photo);
  128. }];
  129. }
  130. #pragma mark - Get Video
  131. - (void)getVideoWithAsset:(PHAsset *)asset completion:(void (^)(AVPlayerItem * _Nullable, NSDictionary * _Nullable))completion {
  132. [[PHImageManager defaultManager] requestPlayerItemForVideo:asset options:nil resultHandler:^(AVPlayerItem * _Nullable playerItem, NSDictionary * _Nullable info) {
  133. if (completion) completion(playerItem,info);
  134. }];
  135. }
  136. #pragma mark - Private Method
  137. - (XG_AlbumModel *)modelWithResult:(PHFetchResult *)result name:(NSString *)name videoPickable:(BOOL)videoPickable{
  138. XG_AlbumModel *model = [[XG_AlbumModel alloc] init];
  139. model.result = result;
  140. model.name = name;
  141. NSMutableArray *assetArr = [NSMutableArray array];
  142. for (PHAsset *asset in result) {
  143. [assetArr addObject:[XG_AssetModel modelWithAsset:asset videoPickable:videoPickable]];
  144. }
  145. model.assetArray = assetArr;
  146. return model;
  147. }
  148. @end