功能实现:
实时监听相册视频文件的增删(文末附GitHub地址);
1.导入库:
#import <Photos/Photos.h>
2.遵守协议:
<PHPhotoLibraryChangeObserver>
3.添加对象:
@property (nonatomic, strong) PHFetchResult *assetsFetchResults;
4.初始化工具类,注册监听,并主动调用一下获取视频的方法(因为第一次启动,监听对象缺少参照):
- (void)startManager { //注册相册的监听
dispatch_async(album_queue(), ^{
self.dataSource = [[NSMutableArray alloc] init];
self.assetsFetchResults = [[PHFetchResult alloc] init];
[[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
[self getAlbumVideoWithBehaviorType:ALBUMVIDEOBEHAVIOR_GETALL PHObjectsArr:nil];
});
}
5.实现监听的方法:
- (void)photoLibraryDidChange:(PHChange *)changeInstance {
//注:监听到动作之后要在主线程做处理
dispatch_async(dispatch_get_main_queue(), ^{
// 监听相册视频发生变化
PHFetchResultChangeDetails *collectionChanges = [changeInstance changeDetailsForFetchResult:self.assetsFetchResults];
if (collectionChanges) {
if ([collectionChanges hasIncrementalChanges]) {
//监听相册视频的增删
//增加了
if (collectionChanges.insertedObjects.count > 0) {
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:collectionChanges.insertedObjects];
[self getAlbumVideoWithBehaviorType:ALBUMVIDEOBEHAVIOR_INSTER PHObjectsArr:mArr];
}
//删除了
if (collectionChanges.removedObjects.count > 0) {
NSMutableArray *mArr = [[NSMutableArray alloc] initWithArray:collectionChanges.removedObjects];
[self getAlbumVideoWithBehaviorType:ALBUMVIDEOBEHAVIOR_REMOVE PHObjectsArr:mArr];
}
/*监听完一次更新一下监听对象*/
self.assetsFetchResults = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeVideo options:[self getFetchPhotosOptions]];
}
}
});
}
6.拿到监听数据,操作添加数据源:
//筛选的规则和范围
- (PHFetchOptions *)getFetchPhotosOptions{
PHFetchOptions *allPhotosOptions = [[PHFetchOptions alloc]init];
//排序的方式为:按时间排序
allPhotosOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]];
return allPhotosOptions;
}
- (void)getAlbumVideoWithBehaviorType:(AlbumVideoBehaviorType)type PHObjectsArr:(NSArray *)phobjectsArr;{
@synchronized(self) {
if (type == ALBUMVIDEOBEHAVIOR_GETALL) {
self.assetsFetchResults = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeVideo options:[self getFetchPhotosOptions]];
if (!self.assetsFetchResults.count) {
[self.dataSource removeAllObjects];
[[NSNotificationCenter defaultCenter] postNotificationName:RefreshAlbumUINotification object:nil];
return;
}
[self.dataSource removeAllObjects];
}
for (PHAsset *videoAsset in type == ALBUMVIDEOBEHAVIOR_GETALL ? self.assetsFetchResults : phobjectsArr) {
[[PHImageManager defaultManager] requestPlayerItemForVideo:videoAsset options:nil resultHandler:^(AVPlayerItem * _Nullable playerItem, NSDictionary * _Nullable info) {
NSString *filePath = [info valueForKey:@"PHImageFileSandboxExtensionTokenKey"];
if (filePath && filePath.length > 0) {
NSArray *lyricArr = [filePath componentsSeparatedByString:@";"];
NSString *privatePath = [lyricArr lastObject];
if (privatePath.length > 8) {
NSString *videoPath = [privatePath substringFromIndex:8];
if (videoPath && videoPath.length > 0) {
NSArray *fieldArr = [videoPath componentsSeparatedByString:@"/"];
if (fieldArr != nil && ![fieldArr isKindOfClass:[NSNull class]] && fieldArr.count != 0) {
if (type == ALBUMVIDEOBEHAVIOR_REMOVE) {
if (self.dataSource.count > 0) {
/**数组的安全遍历*/
NSArray *arr = [NSArray arrayWithArray:self.dataSource];
for (VideoModel *model in arr) {
if ([model.videoName isEqualToString:[fieldArr lastObject]]) {
[self.dataSource removeObject:model];
[self cleanImgWithUseless:model.videoImgPath];
}
}
}
} else {
VideoModel *model = [[VideoModel alloc] init];
model.videoPath = videoPath;
model.videoName = [fieldArr lastObject];
model.videoSize = [SandBoxHelper fileSizeForPath:videoPath];
model.videoImgPath = [self saveImg:[UIImage getThumbnailImage:videoPath] withVideoMid:model.videoName];
model.videoAsset = videoAsset;
[self.dataSource addObject:model];
}
NSLog(@"相册视频数量为 = %ld", self.dataSource.count);
dispatch_async(dispatch_get_main_queue(), ^{ //添加完一个数据,通知页面刷新
[[NSNotificationCenter defaultCenter] postNotificationName:RefreshAlbumUINotification object:nil];
});
}
}
}
}
}];
}
}
}
7.关闭工具的时候注销一下监听:
- (void)stopManager { //注销相册的监听
dispatch_async(dispatch_queue_create(0, 0), ^{
[[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
});
}
将以上代码封装成工具后如何使用:
因为工具的启动是在子线程里完成的,程序启动的时候启动工具
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self getAlbumRightAndSource]; //获取相册权限和数据
}
- (void)getAlbumRightAndSource{
PHAuthorizationStatus author = [PHPhotoLibrary authorizationStatus];
if (author == PHAuthorizationStatusNotDetermined || author == PHAuthorizationStatusRestricted || author == PHAuthorizationStatusDenied) {
PVRLog(@" 用户尚未做出选择这个应用程序的问候||此应用程序没有被授权访问的照片数据 || 用户已经明确否认了这一照片数据的应用程序访问");
}else{
[[AlbumManager shared] startManager];
return;
}
if ([PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusNotDetermined) {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status == PHAuthorizationStatusAuthorized) {
[[AlbumManager shared] startManager];
PVRLog(@"相册授权开启,启动AlbumManager");
}
}];
}
}