From 03fd39eff5686c58657fb1193fe3c52de8049d57 Mon Sep 17 00:00:00 2001 From: QQQ <3671373519@qq.com> Date: Fri, 17 May 2024 20:02:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E5=8F=A6=E4=B8=80=E7=A7=8D?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E7=9A=84=E6=89=B9=E9=87=8F=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YuMi.xcodeproj/project.pbxproj | 6 ++ ...+TabbarViewController_AnimationFileCache.h | 16 +++ ...+TabbarViewController_AnimationFileCache.h | 18 ++++ ...+TabbarViewController_AnimationFileCache.m | 16 +++ .../YMTabbar/View/TabbarViewController.m | 48 +++++---- YuMi/Tools/File/UploadFile.h | 8 +- YuMi/Tools/File/UploadFile.m | 99 ++++++++++++++++++- 7 files changed, 188 insertions(+), 23 deletions(-) create mode 100644 YuMi/Modules/YMTabbar/View/NSObject+TabbarViewController_AnimationFileCache.h create mode 100644 YuMi/Modules/YMTabbar/View/TabbarViewController+TabbarViewController_AnimationFileCache.h create mode 100644 YuMi/Modules/YMTabbar/View/TabbarViewController+TabbarViewController_AnimationFileCache.m diff --git a/YuMi.xcodeproj/project.pbxproj b/YuMi.xcodeproj/project.pbxproj index 94ecd4fe..427ebdde 100644 --- a/YuMi.xcodeproj/project.pbxproj +++ b/YuMi.xcodeproj/project.pbxproj @@ -635,6 +635,7 @@ 9BFE0D8E2898C8C300F53C24 /* XPAnchorCardSkillCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BFE0D8D2898C8C300F53C24 /* XPAnchorCardSkillCollectionViewCell.m */; }; 9BFE0D922899042600F53C24 /* XPTaskCompleteTipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BFE0D912899042600F53C24 /* XPTaskCompleteTipView.m */; }; 9BFE992E288142FD009DA429 /* RoomClassifyModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 9BFE992D288142FD009DA429 /* RoomClassifyModel.m */; }; + 9D63AAD32BF74E82004EFB3B /* TabbarViewController+TabbarViewController_AnimationFileCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D63AAD22BF74E82004EFB3B /* TabbarViewController+TabbarViewController_AnimationFileCache.m */; }; E801274027E323C800BAC3F2 /* XPRoomPKViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E801273F27E323C800BAC3F2 /* XPRoomPKViewController.m */; }; E801274327E323E500BAC3F2 /* XPRoomPKPresenter.m in Sources */ = {isa = PBXBuildFile; fileRef = E801274227E323E500BAC3F2 /* XPRoomPKPresenter.m */; }; E801274727E3241700BAC3F2 /* Api+RoomPK.m in Sources */ = {isa = PBXBuildFile; fileRef = E801274627E3241700BAC3F2 /* Api+RoomPK.m */; }; @@ -2773,6 +2774,8 @@ 9BFE0D912899042600F53C24 /* XPTaskCompleteTipView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPTaskCompleteTipView.m; sourceTree = ""; }; 9BFE992C288142FD009DA429 /* RoomClassifyModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RoomClassifyModel.h; sourceTree = ""; }; 9BFE992D288142FD009DA429 /* RoomClassifyModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RoomClassifyModel.m; sourceTree = ""; }; + 9D63AAD12BF74E82004EFB3B /* TabbarViewController+TabbarViewController_AnimationFileCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TabbarViewController+TabbarViewController_AnimationFileCache.h"; sourceTree = ""; }; + 9D63AAD22BF74E82004EFB3B /* TabbarViewController+TabbarViewController_AnimationFileCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "TabbarViewController+TabbarViewController_AnimationFileCache.m"; sourceTree = ""; }; B66633E061B1B34177CD011C /* Pods-YuMi.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-YuMi.release.xcconfig"; path = "Target Support Files/Pods-YuMi/Pods-YuMi.release.xcconfig"; sourceTree = ""; }; CACF623970097D653132D69A /* Pods_YuMi.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_YuMi.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E801273E27E323C800BAC3F2 /* XPRoomPKViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPRoomPKViewController.h; sourceTree = ""; }; @@ -10093,6 +10096,8 @@ 9BE01AF42893E7E000B50299 /* Cell */, 189DD53226DE255300AB55B1 /* TabbarViewController.h */, 189DD53326DE255300AB55B1 /* TabbarViewController.m */, + 9D63AAD12BF74E82004EFB3B /* TabbarViewController+TabbarViewController_AnimationFileCache.h */, + 9D63AAD22BF74E82004EFB3B /* TabbarViewController+TabbarViewController_AnimationFileCache.m */, 2331C0DA2A5E9E9000E1D940 /* PIFullScreenBannerAnimation.h */, 2331C0DB2A5E9E9000E1D940 /* PIFullScreenBannerAnimation.m */, 142721B029A7647F00C7C423 /* XPBlankViewController.h */, @@ -11726,6 +11731,7 @@ 9B42869528C1E00A009034D2 /* XPRedPacketResultModel.m in Sources */, 2331C16E2A5EB71000E1D940 /* XPNobleAuthorityDescView.m in Sources */, 9BE01AE428937EDE00B50299 /* XPDressUpShopCollectionViewCell.m in Sources */, + 9D63AAD32BF74E82004EFB3B /* TabbarViewController+TabbarViewController_AnimationFileCache.m in Sources */, 1427219129A75F6F00C7C423 /* MultipartMessageHeaderField.m in Sources */, 186A534B26FC6ED900D67B2C /* TTPopupManagerService.m in Sources */, E8BD0F8B28A9EB0A00DE050D /* RoomSailingPrizeListModel.m in Sources */, diff --git a/YuMi/Modules/YMTabbar/View/NSObject+TabbarViewController_AnimationFileCache.h b/YuMi/Modules/YMTabbar/View/NSObject+TabbarViewController_AnimationFileCache.h new file mode 100644 index 00000000..3745cff0 --- /dev/null +++ b/YuMi/Modules/YMTabbar/View/NSObject+TabbarViewController_AnimationFileCache.h @@ -0,0 +1,16 @@ +// +// NSObject+TabbarViewController_AnimationFileCache.h +// YuMi +// +// Created by 123 on 2024/5/17. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface NSObject () + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMTabbar/View/TabbarViewController+TabbarViewController_AnimationFileCache.h b/YuMi/Modules/YMTabbar/View/TabbarViewController+TabbarViewController_AnimationFileCache.h new file mode 100644 index 00000000..3ffa8ef4 --- /dev/null +++ b/YuMi/Modules/YMTabbar/View/TabbarViewController+TabbarViewController_AnimationFileCache.h @@ -0,0 +1,18 @@ +// +// TabbarViewController+TabbarViewController_AnimationFileCache.h +// YuMi +// +// Created by 123 on 2024/5/17. +// + +#import "TabbarViewController.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TabbarViewController (TabbarViewController_AnimationFileCache) + +- (void)cacheAnimationResources; + +@end + +NS_ASSUME_NONNULL_END diff --git a/YuMi/Modules/YMTabbar/View/TabbarViewController+TabbarViewController_AnimationFileCache.m b/YuMi/Modules/YMTabbar/View/TabbarViewController+TabbarViewController_AnimationFileCache.m new file mode 100644 index 00000000..fa2e90fe --- /dev/null +++ b/YuMi/Modules/YMTabbar/View/TabbarViewController+TabbarViewController_AnimationFileCache.m @@ -0,0 +1,16 @@ +// +// TabbarViewController+TabbarViewController_AnimationFileCache.m +// YuMi +// +// Created by 123 on 2024/5/17. +// + +#import "TabbarViewController+TabbarViewController_AnimationFileCache.h" + +@implementation TabbarViewController (TabbarViewController_AnimationFileCache) + +- (void)cacheAnimationResources { + +} + +@end diff --git a/YuMi/Modules/YMTabbar/View/TabbarViewController.m b/YuMi/Modules/YMTabbar/View/TabbarViewController.m index 5da69883..e7474dff 100644 --- a/YuMi/Modules/YMTabbar/View/TabbarViewController.m +++ b/YuMi/Modules/YMTabbar/View/TabbarViewController.m @@ -126,6 +126,9 @@ UIKIT_EXTERN NSString *kTabShowAnchorCardKey; @property(nonatomic,strong) PIFullScreenBannerAnimation *roomAnimation; +@property(nonatomic, assign) NSInteger allResourcesCount; +@property(nonatomic, assign) NSInteger downloadedResourcesCount; + @end @implementation TabbarViewController @@ -334,32 +337,38 @@ UIKIT_EXTERN NSString *kTabShowAnchorCardKey; } ///缓存礼物特效 -(void)requestGiftList{ - + NSLog(@"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 开始时间:%@", [NSDate date]); @kWeakify(self); - [[AFNetworkReachabilityManager sharedManager] startMonitoring]; - [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { + AFNetworkReachabilityManager *networkManager = [AFNetworkReachabilityManager sharedManager]; + [networkManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { @kStrongify(self); switch (status) { case AFNetworkReachabilityStatusUnknown: + [[UploadFile share] pasuBatchDownload]; break; case AFNetworkReachabilityStatusNotReachable: - + [[UploadFile share] pasuBatchDownload]; break; case AFNetworkReachabilityStatusReachableViaWWAN: case AFNetworkReachabilityStatusReachableViaWiFi: { if(self.isFirstReachability == NO){ - [self dealWithDefaultSvga]; - [self dealWithGiftList]; +// [self dealWithDefaultSvga]; +// [self removeCacheFromOldMethod]; [Api requestCacheGiftDynamicEffectList:^(BaseModel * _Nullable data, NSInteger code, NSString * _Nullable msg) { if(code == 200){ - self.isFirstReachability = YES; - NSArray *list = data.data; - NSSet *setList = [[NSSet alloc]initWithArray:list];///去重,防止有重复的 - for (NSString *url in setList) { + self.isFirstReachability = YES; // MARK: 只在第一次有 wifi 情况进入下载,其实后续变化也没有影响 =。= + // 所以用 Monitor 也没有太大必要 -> 修改为真正的批量下载方法 + NSArray *allResourceList = data.data; + NSSet *allResourceSet = [[NSSet alloc] initWithArray:allResourceList]; + NSMutableArray *allResourceURLs = @[].mutableCopy; + for (NSString *url in allResourceSet) { NSString *encodingUrl = [url stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet characterSetWithCharactersInString:@"`#%^{}\"[]|\\<> "].invertedSet]; - [self cacheGiftDynamicEffectList:encodingUrl]; + [allResourceURLs addObject:encodingUrl]; +// [self cacheGiftDynamicEffectList:encodingUrl]; } + [[UploadFile share] startBatchDownloadWithURLs:allResourceURLs]; + NSLog(@"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 资源总数:%ld", (unsigned long)allResourceURLs.count); } }]; } @@ -371,7 +380,7 @@ UIKIT_EXTERN NSString *kTabShowAnchorCardKey; } }]; - + [networkManager startMonitoring]; } -(void)dealWithDefaultSvga{ @@ -387,7 +396,7 @@ UIKIT_EXTERN NSString *kTabShowAnchorCardKey; -(void)cacheGiftDynamicEffectList:(NSString *)url{ NSString *fileName = [[url componentsSeparatedByString:@"/"] lastObject]; - NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) safeObjectAtIndex1:0] stringByAppendingPathComponent:@"GiftDynamicEffectList"]; + NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) safeObjectAtIndex1:0] stringByAppendingPathComponent:@"GiftDynamicEffectList"]; // MARK: 这个 path 会被混淆影响吗? NSString *fullPath = [filePath stringByAppendingPathComponent:fileName]; if ([[NSFileManager defaultManager] fileExistsAtPath:fullPath]) { return; @@ -396,15 +405,16 @@ UIKIT_EXTERN NSString *kTabShowAnchorCardKey; [fileMgr createDirectoryAtPath:filePath withIntermediateDirectories:YES attributes:nil error:nil]; [UploadFile downloadAudioWithFileName:fileName musicUrl:url mainFileName:@"GiftDynamicEffectList" completion:^(BOOL isSuccess, NSString *editAudioPath) { if(isSuccess){ - - + NSLog("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 原方法下载成功:%@, 时间:%@", editAudioPath, [NSDate date]); }else{ - + NSLog("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 原方法下载失败:%@", [NSDate date]); } + self.downloadedResourcesCount+=1; + NSLog(@"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 已处理资源资源:%ld", (long)self.downloadedResourcesCount); }]; } --(void)dealWithGiftList{ - ///删除旧数据缓存, +-(void)removeCacheFromOldMethod{ + ///删除旧数据缓存,预计 2 个版本后可以删除此方法 NSString *svgaFileName = @"/GiftSvga"; NSString *svgaFilePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:svgaFileName]; if ([[NSFileManager defaultManager] fileExistsAtPath:svgaFilePath]) { @@ -412,7 +422,6 @@ UIKIT_EXTERN NSString *kTabShowAnchorCardKey; if(isSuccess == YES){ NSLog(@"删除成功"); } - } NSString *mp4FileName = @"/GiftMp4"; @@ -422,7 +431,6 @@ UIKIT_EXTERN NSString *kTabShowAnchorCardKey; if(isSuccess == YES){ NSLog(@"删除成功"); } - } } diff --git a/YuMi/Tools/File/UploadFile.h b/YuMi/Tools/File/UploadFile.h index 51e4ae01..8c387c26 100644 --- a/YuMi/Tools/File/UploadFile.h +++ b/YuMi/Tools/File/UploadFile.h @@ -37,7 +37,13 @@ NS_ASSUME_NONNULL_BEGIN failure:(void (^)(NSNumber *resCode, NSString *message))failure; ///下载资料 --(void)downloadAnimationFileName:(NSString *)fileName localPath:(NSString *)localPath completion:(void (^) (BOOL isSuccess, NSString *editAudioPath))completion; +- (void)downloadAnimationFileName:(NSString *)fileName localPath:(NSString *)localPath completion:(void (^) (BOOL isSuccess, NSString *editAudioPath))completion; + +// 批量下载 +- (void)startBatchDownloadWithURLs:(NSArray *)URLs; +- (void)pasuBatchDownload; +- (void)resumeBatchDownload; + @end NS_ASSUME_NONNULL_END diff --git a/YuMi/Tools/File/UploadFile.m b/YuMi/Tools/File/UploadFile.m index 1c909f79..da5adb3c 100644 --- a/YuMi/Tools/File/UploadFile.m +++ b/YuMi/Tools/File/UploadFile.m @@ -15,6 +15,12 @@ static UploadFile* manager; // 一个脚手架实例 @property (nonatomic) QCloudCredentailFenceQueue* credentialFenceQueue; @property(nonatomic,strong) UploadFileModel *fileModel; + +// MARK: 批量下载部分, 后续要新建一个 object 来承载业务 +@property (nonatomic, strong) AFHTTPSessionManager *manager; +@property (nonatomic, strong) NSData *resumeData; +@property (nonatomic, strong) NSMutableArray *tasks; + @end @implementation UploadFile @@ -258,9 +264,12 @@ static UploadFile* manager; [[QCloudCOSTransferMangerService defaultCOSTransferManager] DownloadObject:request]; } -+(void)downloadAudioWithFileName:(NSString *)fileName musicUrl:(NSString *)musicUrl mainFileName:(NSString *)mainFileName completion:(void (^) (BOOL isSuccess, NSString *editAudioPath))completion { ++(void)downloadAudioWithFileName:(NSString *)fileName + musicUrl:(NSString *)musicUrl + mainFileName:(NSString *)mainFileName + completion:(void (^) (BOOL isSuccess, NSString *editAudioPath))completion { AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; - NSURL *url = [NSURL URLWithString:[musicUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]]; + NSURL *url = [NSURL URLWithString:[musicUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]]; NSURLRequest *request = [NSURLRequest requestWithURL :url]; NSURLSessionDownloadTask *download = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { @@ -275,4 +284,90 @@ static UploadFile* manager; }]; [download resume]; } + +// 批量下载 +- (void)startBatchDownloadWithURLs:(NSArray *)URLs { + if (_manager == nil) { + _manager = [AFHTTPSessionManager manager]; + _manager.operationQueue.maxConcurrentOperationCount = 10; + _tasks = [NSMutableArray array]; + } + + if (URLs.count == 0) { + return; + } + + NSMutableArray *errors = [NSMutableArray array]; + NSMutableArray *filePaths = [NSMutableArray array]; + + for (NSString *urlStr in URLs) { + NSURL *url = [NSURL URLWithString:urlStr]; + NSURLRequest *request = [NSURLRequest requestWithURL:url]; + + // 获取目标文件路径 + NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; + NSURL *destinationURL = [documentsDirectoryURL URLByAppendingPathComponent:[url lastPathComponent]]; + + // 检查文件是否已经存在 + if ([[NSFileManager defaultManager] fileExistsAtPath:[destinationURL path]]) { + NSLog(@"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 文件已存在,跳过下载: %@", destinationURL); + [filePaths addObject:destinationURL]; + continue; + } + + NSURLSessionDownloadTask *downloadTask = [self.manager downloadTaskWithRequest:request + progress:nil + destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { + // 下载目标位置 + return destinationURL; + } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { + if (error) { + [errors addObject:error]; + NSLog("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 下载失败:%@, %@", error, [NSDate date]); + } else { + [filePaths addObject:filePath]; + NSLog("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 下载成功:%@, 时间:%@", filePath, [NSDate date]); + } + if (filePaths.count + errors.count == URLs.count) { + // 全部任务处理完成 + NSLog(@"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 资源总数:%ld, %@", (unsigned long)URLs.count, [NSDate date]); + } + }]; + + [self.tasks addObject:downloadTask]; + } + + for (NSURLSessionDownloadTask *task in self.tasks) { + [task resume]; + } +} + +- (void)pasuBatchDownload { + NSLog(@"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 暂停下载"); + for (NSURLSessionDownloadTask *task in self.tasks) { + [task cancelByProducingResumeData:^(NSData * _Nullable resumeData) { + if (resumeData) { + self.resumeData = resumeData; + } + }]; + } +} + +- (void)resumeBatchDownload { + if (self.resumeData) { + NSURLSessionDownloadTask *downloadTask = [self.manager downloadTaskWithResumeData:self.resumeData progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { + NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil]; + return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]]; + } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { + if (error) { + NSLog(@"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 续传下载失败: %@", error.localizedDescription); + } else { + NSLog(@"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 续传下载文件保存到: %@", filePath); + } + }]; + + [downloadTask resume]; + } +} + @end