Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

监听系统相册变化,更新数据源和界面。 #1083

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions QMUIKit/QMUIComponents/AssetLibrary/QMUIAssetFetchResultChange.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Tencent is pleased to support the open source community by making QMUI_iOS available.
* Copyright (C) 2016-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/

//
// QMUIAssetFetchResultChange.h
// qmui
//
// Created by QMUI Team on 20/8/29.
//

#import <Foundation/Foundation.h>
#import "QMUIAssetsGroup.h"

@class PHFetchResultChangeDetails;

NS_ASSUME_NONNULL_BEGIN

@interface QMUIAssetFetchResultChange : NSObject

@property (nonatomic, readonly) BOOL hasIncrementalChanges;

@property (nonatomic, readonly) BOOL hasMoves;

@property (nonatomic, readonly) NSArray <NSIndexPath *> *removedIndexPaths;

@property (nonatomic, readonly) NSArray <NSIndexPath *> *insertedIndexPaths;

@property (nonatomic, readonly) NSArray <NSIndexPath *> *changedIndexPaths;


- (instancetype)initWithChangeDetails:(PHFetchResultChangeDetails <PHAsset *> *)changeDetails
albumSortType:(QMUIAlbumSortType)albumSortType;

- (void)enumerateMovesWithBlock:(void(^)(NSIndexPath *fromIndexPath, NSIndexPath *toIndexPath))handler;

@end

NS_ASSUME_NONNULL_END
95 changes: 95 additions & 0 deletions QMUIKit/QMUIComponents/AssetLibrary/QMUIAssetFetchResultChange.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* Tencent is pleased to support the open source community by making QMUI_iOS available.
* Copyright (C) 2016-2020 THL A29 Limited, a Tencent company. All rights reserved.
* Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
* http://opensource.org/licenses/MIT
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/

//
// QMUIAssetFetchResultChange.m
// qmui
//
// Created by QMUI Team on 20/8/29.
//

#import "QMUIAssetFetchResultChange.h"
#import <Photos/Photos.h>

@interface QMUIAssetFetchResultChangeMovePair : NSObject

@property (nonatomic, strong) NSIndexPath *fromIndexPath;

@property (nonatomic, strong) NSIndexPath *toIndexPath;

@end

@implementation QMUIAssetFetchResultChangeMovePair

@end

@interface QMUIAssetFetchResultChange ()

@property (nonatomic, strong) NSMutableArray <QMUIAssetFetchResultChangeMovePair *> *movePairs;

@end

@implementation QMUIAssetFetchResultChange

- (instancetype)initWithChangeDetails:(PHFetchResultChangeDetails<PHAsset *> *)changeDetails
albumSortType:(QMUIAlbumSortType)albumSortType {
self = [super init];
if (self) {
_hasIncrementalChanges = changeDetails.hasIncrementalChanges;
_hasMoves = changeDetails.hasMoves;
const NSUInteger countAfterChanges = changeDetails.fetchResultAfterChanges.count;
_removedIndexPaths = [self indexPathsForIndexSet:changeDetails.removedIndexes
albumSortType:albumSortType
count:changeDetails.fetchResultBeforeChanges.count];
_insertedIndexPaths = [self indexPathsForIndexSet:changeDetails.insertedIndexes
albumSortType:albumSortType
count:countAfterChanges];
_changedIndexPaths = [self indexPathsForIndexSet:changeDetails.changedIndexes
albumSortType:albumSortType
count:countAfterChanges];
NSMutableArray <QMUIAssetFetchResultChangeMovePair *> *movePairs = [[NSMutableArray alloc] init];
[changeDetails enumerateMovesWithBlock:^(NSUInteger fromIndex, NSUInteger toIndex) {
QMUIAssetFetchResultChangeMovePair *movePair = [[QMUIAssetFetchResultChangeMovePair alloc] init];
movePair.fromIndexPath = [NSIndexPath indexPathForItem:[self convertIndex:fromIndex
albumSortType:albumSortType
count:countAfterChanges]
inSection:0];
movePair.toIndexPath = [NSIndexPath indexPathForItem:[self convertIndex:toIndex
albumSortType:albumSortType
count:countAfterChanges]
inSection:0];
[movePairs addObject:movePair];
}];
_movePairs = movePairs;
}
return self;
}

- (void)enumerateMovesWithBlock:(void (^)(NSIndexPath * _Nonnull, NSIndexPath * _Nonnull))handler {

}

#pragma mark - Private
- (NSArray <NSIndexPath *> *)indexPathsForIndexSet:(NSIndexSet *)indexSet
albumSortType:(QMUIAlbumSortType)albumSortType
count:(NSUInteger)count {
NSMutableArray <NSIndexPath *> *indexPaths = [[NSMutableArray alloc] init];
[indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
[indexPaths addObject:[NSIndexPath indexPathForItem:[self convertIndex:idx
albumSortType:albumSortType
count:count]
inSection:0]];
}];
return indexPaths;
}

- (NSUInteger)convertIndex:(NSUInteger)index albumSortType:(QMUIAlbumSortType)albumSortType count:(NSUInteger)count {
return albumSortType == QMUIAlbumSortTypeReverse ? count - 1 - index : index;
}

@end
4 changes: 3 additions & 1 deletion QMUIKit/QMUIComponents/AssetLibrary/QMUIAssetsGroup.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,16 @@ typedef NS_ENUM(NSUInteger, QMUIAlbumSortType) {
@property(nonatomic, strong, readonly) PHAssetCollection *phAssetCollection;

/// 仅能通过 initWithPHCollection 和 initWithPHCollection:fetchAssetsOption 方法修改 phAssetCollection 后,产生一个对应的 PHAssetsFetchResults 保存到 phFetchResult 中
@property(nonatomic, strong, readonly) PHFetchResult *phFetchResult;
@property(nonatomic, strong) PHFetchResult <PHAsset *> *phFetchResult;

/// 相册的名称
- (NSString *)name;

/// 相册内的资源数量,包括视频、图片、音频(如果支持)这些类型的所有资源
- (NSInteger)numberOfAssets;

- (NSInteger)convertedIndexForIndex:(NSInteger)index albumSortType:(QMUIAlbumSortType)albumSortType;

/**
* 相册的缩略图,即系统接口中的相册海报(Poster Image)
*
Expand Down
9 changes: 8 additions & 1 deletion QMUIKit/QMUIComponents/AssetLibrary/QMUIAssetsGroup.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
@interface QMUIAssetsGroup()

@property(nonatomic, strong, readwrite) PHAssetCollection *phAssetCollection;
@property(nonatomic, strong, readwrite) PHFetchResult *phFetchResult;

@end

Expand All @@ -44,6 +43,14 @@ - (NSInteger)numberOfAssets {
return self.phFetchResult.count;
}

- (NSInteger)convertedIndexForIndex:(NSInteger)index albumSortType:(QMUIAlbumSortType)albumSortType {
if (albumSortType == QMUIAlbumSortTypeReverse) {
return self.phFetchResult.count - 1 - index;
} else {
return index;
}
}

- (NSString *)name {
NSString *resultName = self.phAssetCollection.localizedTitle;
return NSLocalizedString(resultName, resultName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#import "QMUIImagePickerViewController.h"
#import "QMUIImagePickerHelper.h"
#import "QMUIAppearance.h"
#import "QMUIAssetFetchResultChange.h"
#import <Photos/PHPhotoLibrary.h>
#import <Photos/PHAsset.h>
#import <Photos/PHFetchOptions.h>
Expand Down Expand Up @@ -125,14 +126,18 @@ + (void)initAppearance {

#pragma mark - QMUIAlbumViewController

@interface QMUIAlbumViewController ()
@interface QMUIAlbumViewController () <PHPhotoLibraryChangeObserver>

@property(nonatomic, strong) NSMutableArray<QMUIAssetsGroup *> *albumsArray;
@property(nonatomic, strong) QMUIImagePickerViewController *imagePickerViewController;
@end

@implementation QMUIAlbumViewController

- (void)dealloc {
[[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
}

- (void)didInitialize {
[super didInitialize];
_shouldShowDefaultLoadingView = YES;
Expand All @@ -154,6 +159,8 @@ - (void)initTableView {

- (void)viewDidLoad {
[super viewDidLoad];
[[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];

if ([QMUIAssetsManager authorizationStatus] == QMUIAssetAuthorizationStatusNotAuthorized) {
// 如果没有获取访问授权,或者访问授权状态已经被明确禁止,则显示提示语,引导用户开启授权
NSString *tipString = self.tipTextWhenNoPhotosAuthorization;
Expand Down Expand Up @@ -214,11 +221,11 @@ - (void)refreshAlbumAndShowEmptyTipIfNeed {
if (self.shouldShowDefaultLoadingView) {
[self hideEmptyView];
}
[self.tableView reloadData];
} else {
NSString *tipString = self.tipTextWhenPhotosEmpty ? : @"空照片";
[self showEmptyViewWithText:tipString detailText:nil buttonTitle:nil buttonAction:nil];
}
[self.tableView reloadData];
}

- (void)pickAlbumsGroup:(QMUIAssetsGroup *)assetsGroup animated:(BOOL)animated {
Expand Down Expand Up @@ -277,4 +284,23 @@ - (void)handleCancelSelectAlbum:(id)sender {
}];
}

#pragma mark - PHPhotoLibraryChangeObserver

- (void)photoLibraryDidChange:(PHChange *)changeInstance {
NSMutableArray <QMUIAssetsGroup *> *albums = [[NSMutableArray alloc] init];
[[QMUIAssetsManager sharedInstance] enumerateAllAlbumsWithAlbumContentType:self.contentType usingBlock:^(QMUIAssetsGroup *resultAssetsGroup) {
if (resultAssetsGroup) {
[albums addObject:resultAssetsGroup];
} else {
dispatch_async(dispatch_get_main_queue(), ^{
self.albumsArray = albums;
[self sortAlbumArray];
[self refreshAlbumAndShowEmptyTipIfNeed];
if (self.imagePickerViewController) {
[self.imagePickerViewController updateCollectionViewWithChangeInstance:changeInstance];
}
});
}
}];
}
@end
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
#import <UIKit/UIKit.h>
#import "QMUIImagePreviewViewController.h"
#import "QMUIAsset.h"
#import "QMUIAssetsGroup.h"

NS_ASSUME_NONNULL_BEGIN

@class QMUIButton, QMUINavigationButton;
@class QMUIImagePickerViewController;
@class QMUIImagePickerPreviewViewController;
@class QMUIAssetFetchResultChange;

@protocol QMUIImagePickerPreviewViewControllerDelegate <NSObject>

Expand Down Expand Up @@ -52,10 +54,6 @@ NS_ASSUME_NONNULL_BEGIN
@property(nullable, nonatomic, strong, readonly) QMUINavigationButton *backButton;
@property(nullable, nonatomic, strong, readonly) QMUIButton *checkboxButton;

/// 由于组件需要通过本地图片的 QMUIAsset 对象读取图片的详细信息,因此这里的需要传入的是包含一个或多个 QMUIAsset 对象的数组
@property(nullable, nonatomic, strong) NSMutableArray<QMUIAsset *> *imagesAssetArray;
@property(nullable, nonatomic, strong) NSMutableArray<QMUIAsset *> *selectedImageAssetArray;

@property(nonatomic, assign) QMUIAssetDownloadStatus downloadStatus;

/// 最多可以选择的图片数,默认为无穷大
Expand All @@ -67,6 +65,11 @@ NS_ASSUME_NONNULL_BEGIN
/// 选择图片超出最大图片限制时 alertView 的标题
@property(nullable, nonatomic, copy) NSString *alertButtonTitleWhenExceedMaxSelectImageCount;

/// 已选照片,单选模式下为 nil
@property (nonatomic, strong, nullable) NSMutableArray <QMUIAsset *> *selectedImageAssetArray;

/// 照片排序方式
@property (nonatomic, assign) QMUIAlbumSortType albumSortType;
/**
* 更新数据并刷新 UI,手工调用
*
Expand All @@ -75,10 +78,16 @@ NS_ASSUME_NONNULL_BEGIN
* @param currentImageIndex 当前展示的图片在 imageAssetArray 的索引
* @param singleCheckMode 是否为单选模式,如果是单选模式,则不显示 checkbox
*/
- (void)updateImagePickerPreviewViewWithImagesAssetArray:(NSMutableArray<QMUIAsset *> * _Nullable)imageAssetArray
selectedImageAssetArray:(NSMutableArray<QMUIAsset *> * _Nullable)selectedImageAssetArray
currentImageIndex:(NSInteger)currentImageIndex
singleCheckMode:(BOOL)singleCheckMode;
- (void)updateImagePickerPreviewViewWithAssetGroup:(QMUIAssetsGroup *)assetGroup
imagesAssets:(NSMutableDictionary <NSString *, QMUIAsset *> *)imageAssets
selectedImageAssetArray:(NSMutableArray<QMUIAsset *> * _Nullable)selectedImageAssetArray
currentImageIndex:(NSInteger)currentImageIndex
singleCheckMode:(BOOL)singleCheckMode
onlyPreviewSelectedImageAssets:(BOOL)onlyPreviewSelectedImageAssets;

- (void)updateCollectionViewWithAssetFetchResultChange:(QMUIAssetFetchResultChange *)assetFetchResultChange;

- (QMUIAsset *)imageAssetForIndex:(NSInteger)index;

@end

Expand Down
Loading