小说绘上架版本
This commit is contained in:
+30
@@ -0,0 +1,30 @@
|
||||
//
|
||||
// WXYZ_AudioDownloadManager.h
|
||||
// WXReader
|
||||
//
|
||||
// Created by Andrew on 2020/3/28.
|
||||
// Copyright © 2020 Andrew. All rights reserved.
|
||||
//
|
||||
|
||||
#import "WXYZ_DownloadHelper.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface WXYZ_AudioDownloadManager : NSObject <WXYZ_DownloadManagerProtocol>
|
||||
|
||||
@property (nonatomic, copy) void (^downloadDeleteFinishBlock)(NSArray *success_chapter_ids, NSArray *fail_chapter);
|
||||
|
||||
// 章节下载状态改变
|
||||
@property (nonatomic, copy) void (^downloadChapterStateChangeBlock)(WXYZ_DownloadChapterState state, NSInteger production_id, NSInteger chapter_id);
|
||||
|
||||
// 总体任务下载完成
|
||||
@property (nonatomic, copy) void (^downloadMissionStateChangeBlock)(WXYZ_DownloadMissionState state, NSInteger production_id, NSArray *chapter_ids);
|
||||
|
||||
interface_singleton
|
||||
|
||||
// 获取已下载音频文件路径
|
||||
- (NSString *)chapterDownloadedFilePathWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id chapter_update_time:(NSString *)chapter_update_time;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
//
|
||||
// WXYZ_AudioDownloadManager.m
|
||||
// WXReader
|
||||
//
|
||||
// Created by Andrew on 2020/3/28.
|
||||
// Copyright © 2020 Andrew. All rights reserved.
|
||||
//
|
||||
|
||||
#import "WXYZ_AudioDownloadManager.h"
|
||||
|
||||
static dispatch_group_t url_session_manager_completion_group() {
|
||||
static dispatch_group_t af_url_session_manager_completion_group;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
af_url_session_manager_completion_group = dispatch_group_create();
|
||||
});
|
||||
|
||||
return af_url_session_manager_completion_group;
|
||||
}
|
||||
|
||||
@interface WXYZ_AudioDownloadManager () <NSURLSessionDataDelegate>
|
||||
|
||||
@property (nonatomic, assign) BOOL requesting;
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray *requestOrderArray;
|
||||
|
||||
@end
|
||||
|
||||
@implementation WXYZ_AudioDownloadManager
|
||||
|
||||
implementation_singleton(WXYZ_AudioDownloadManager)
|
||||
|
||||
/*
|
||||
增
|
||||
**/
|
||||
|
||||
// 下载章节
|
||||
- (void)downloadChapterWithProductionModel:(TFProductionModel *)productionModel production_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id
|
||||
{
|
||||
[self downloadChaptersWithProductionModel:productionModel production_id:production_id chapter_ids:@[[TFUtilsHelper formatStringWithInteger:chapter_id]]];
|
||||
}
|
||||
|
||||
// 下载多个章节
|
||||
- (void)downloadChaptersWithProductionModel:(TFProductionModel *)productionModel production_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *>*)chapter_ids
|
||||
{
|
||||
[[WXYZ_DownloadHelper sharedManager] recordDownloadProductionWithProductionModel:productionModel productionType:TFProductionTypeAudio];
|
||||
|
||||
WS(weakSelf)
|
||||
[TFNetworkTools POST:Audio_Chapter_Download parameters:@{@"audio_id":[TFUtilsHelper formatStringWithInteger:production_id], @"chapter_id":[chapter_ids componentsJoinedByString:@","]} model:nil success:^(BOOL isSuccess, NSDictionary * _Nullable t_model, TFNetworkRequestModel * _Nonnull requestModel) {
|
||||
if (isSuccess) {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// 任务开始
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionStart, production_id, chapter_ids);
|
||||
}
|
||||
// 任务加入任务队列
|
||||
NSArray *taskArray = [t_model objectForKey:@"data"];
|
||||
if (taskArray.count > 0) {
|
||||
|
||||
for (NSDictionary *t_dic in taskArray) {
|
||||
TFProductionChapterModel *imageCollectionModel = [TFProductionChapterModel modelWithDictionary:t_dic];
|
||||
if (imageCollectionModel) {
|
||||
// 开始下载
|
||||
[[self audioChaptersRecordDictionaryWithProduction_id:imageCollectionModel.production_id] setObject:identify_downloading forKey:chapterRecordKey(imageCollectionModel.production_id, imageCollectionModel.chapter_id)];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.downloadChapterStateChangeBlock) {
|
||||
self.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadStart, imageCollectionModel.production_id, imageCollectionModel.chapter_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[weakSelf.requestOrderArray addObject:taskArray];
|
||||
|
||||
if (!weakSelf.requesting) {
|
||||
[TFPromptManager showPromptViewWithStatus:TFPromptStatusSuccess promptTitle:TFLocalizedString(@"已加入下载列表")];
|
||||
}
|
||||
|
||||
// 开始下载任务
|
||||
[weakSelf downloadTaskRequest];
|
||||
} else {
|
||||
// 任务失败
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, chapter_ids);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
} else if (Compare_Json_isEqualTo(requestModel.code, 701)) { // 请求购买
|
||||
|
||||
// 任务失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionShouldPay, production_id, chapter_ids);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
[TFPromptManager showPromptViewWithStatus:TFPromptStatusError promptTitle:requestModel.msg];
|
||||
|
||||
// 任务失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, chapter_ids);
|
||||
}
|
||||
});
|
||||
}
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
|
||||
// 任务失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, chapter_ids);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
/*
|
||||
删
|
||||
**/
|
||||
|
||||
// 删除本地已下载作品
|
||||
- (BOOL)removeDownloadProductionWithProduction_id:(NSInteger)production_id
|
||||
{
|
||||
// 删除作品文件夹
|
||||
[[WXYZ_DownloadHelper sharedManager] removeDownloadProductionFolderWithProduction_id:production_id productionType:TFProductionTypeAudio];
|
||||
|
||||
// 删除缓存
|
||||
[[self audioChaptersRecordDictionaryWithProduction_id:production_id] removeAllObjects];
|
||||
|
||||
// 写入
|
||||
[self audioRecordWriteToPlistWithProduction_id:production_id];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
// 删除本地多个已下载章节
|
||||
- (void)removeDownloadChaptersWithProduction_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *> *)chapter_ids
|
||||
{
|
||||
if (chapter_ids.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 删除文件夹
|
||||
[[WXYZ_DownloadHelper sharedManager] removeDownloadChapterFolderWithProduction_id:production_id chapter_ids:chapter_ids productionType:TFProductionTypeAudio];
|
||||
|
||||
// 删除下载记录
|
||||
NSMutableDictionary *t_dic = [self audioChaptersRecordDictionaryWithProduction_id:production_id];
|
||||
|
||||
NSMutableArray *t_delete_arr = [NSMutableArray array];
|
||||
for (NSString *chapter_id in chapter_ids) {
|
||||
[t_delete_arr addObject:chapterRecordKey(production_id, [chapter_id integerValue])];
|
||||
}
|
||||
|
||||
[t_dic removeObjectsForKeys:t_delete_arr];
|
||||
|
||||
// 如果全部章节已经删除,则删除整体作品文件夹
|
||||
if ([self getDownloadChapterCountWithProduction_id:production_id] == 0) {
|
||||
[self removeDownloadProductionWithProduction_id:production_id];
|
||||
} else {
|
||||
[self audioRecordWriteToPlistWithProduction_id:production_id];
|
||||
}
|
||||
|
||||
// 删除回调
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.downloadDeleteFinishBlock) {
|
||||
self.downloadDeleteFinishBlock(chapter_ids, @[]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
查
|
||||
**/
|
||||
|
||||
// 获取下载章节数
|
||||
- (NSInteger)getDownloadChapterCountWithProduction_id:(NSInteger)production_id
|
||||
{
|
||||
return [[WXYZ_DownloadHelper sharedManager] getDownloadChapterCountWithProduction_id:production_id productionType:TFProductionTypeAudio];
|
||||
}
|
||||
|
||||
// 获取全部已下载章节model
|
||||
- (NSArray *)getDownloadChapterModelArrayWithProduction_id:(NSInteger)production_id
|
||||
{
|
||||
NSMutableDictionary *t_dic = [self audioChaptersRecordDictionaryWithProduction_id:production_id];
|
||||
|
||||
NSMutableArray *t_arr = [NSMutableArray array];
|
||||
for (id value in t_dic.allValues) {
|
||||
if ([value isKindOfClass:[TFProductionChapterModel class]]) {
|
||||
[t_arr addObject:value];
|
||||
}
|
||||
}
|
||||
return [t_arr copy];
|
||||
}
|
||||
|
||||
// 获取已下载章节model
|
||||
- (id)getDownloadChapterModelWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id
|
||||
{
|
||||
NSMutableDictionary *t_dic = [self audioChaptersRecordDictionaryWithProduction_id:production_id];
|
||||
|
||||
id value = [t_dic objectForKey:chapterRecordKey(production_id, chapter_id)];
|
||||
|
||||
if ([value isKindOfClass:[TFProductionChapterModel class]]) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
// 获取章节下载状态
|
||||
- (WXYZ_ProductionDownloadState)getChapterDownloadStateWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id
|
||||
{
|
||||
NSMutableDictionary *t_dic = [self audioChaptersRecordDictionaryWithProduction_id:production_id];
|
||||
if ([[t_dic objectForKey:chapterRecordKey(production_id, chapter_id)] isEqual:identify_downloading]) {
|
||||
return WXYZ_ProductionDownloadStateDownloading;
|
||||
}
|
||||
|
||||
if ([[t_dic objectForKey:chapterRecordKey(production_id, chapter_id)] isKindOfClass:[TFProductionChapterModel class]]) {
|
||||
return WXYZ_ProductionDownloadStateDownloaded;
|
||||
}
|
||||
|
||||
return WXYZ_ProductionDownloadStateNormal;
|
||||
}
|
||||
|
||||
// 作品章节是否下载
|
||||
- (BOOL)isChapterDownloadedWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id
|
||||
{
|
||||
return [[WXYZ_DownloadHelper sharedManager] isChapterDownloadedWithProduction_id:production_id chapter_id:chapter_id productionType:TFProductionTypeAudio];
|
||||
}
|
||||
|
||||
// 获取文件地址
|
||||
- (NSString *)chapterDownloadedFilePathWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id chapter_update_time:(NSString *)chapter_update_time
|
||||
{
|
||||
// 章节文件名称
|
||||
NSString *chapterFileName = [TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@", [TFUtilsHelper formatStringWithInteger:production_id], [TFUtilsHelper formatStringWithInteger:chapter_id], [TFUtilsHelper formatStringWithObject:chapter_update_time]]];
|
||||
|
||||
NSString *chapterFilePath = @"";
|
||||
NSArray *extensionArr = @[@"mp3", @"wav", @"wma"];
|
||||
for (NSString *extension in extensionArr) {
|
||||
chapterFilePath = [[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:production_id chapter_id:chapter_id productionType:TFProductionTypeAudio] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", chapterFileName, extension]];
|
||||
if (chapterFilePath && chapterFilePath.length > 0 && [[NSFileManager defaultManager] fileExistsAtPath:chapterFilePath]) {
|
||||
return chapterFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
return chapterFilePath;
|
||||
}
|
||||
|
||||
- (void)downloadTaskRequest
|
||||
{
|
||||
if (self.requestOrderArray.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.requesting) {
|
||||
return;
|
||||
}
|
||||
self.requesting = YES;
|
||||
|
||||
NSArray *taskArray = [self.requestOrderArray firstObject];
|
||||
[self.requestOrderArray removeFirstObject];
|
||||
|
||||
WS(weakSelf)
|
||||
dispatch_group_async(url_session_manager_completion_group(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
|
||||
dispatch_queue_t audio_queue = dispatch_queue_create("wxyz_audio_queue", DISPATCH_QUEUE_CONCURRENT);
|
||||
dispatch_group_t audio_group = dispatch_group_create();
|
||||
|
||||
for (NSDictionary *t_dic in taskArray) {
|
||||
dispatch_group_async(audio_group, audio_queue, ^{
|
||||
|
||||
dispatch_group_enter(audio_group);
|
||||
|
||||
TFProductionChapterModel *t_model = [TFProductionChapterModel modelWithDictionary:t_dic];
|
||||
|
||||
if (!t_model) {
|
||||
// 单个章节下载失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadChapterStateChangeBlock) {
|
||||
weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFail, t_model.production_id, t_model.chapter_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
AFURLSessionManager *manager = [[AFURLSessionManager alloc] init];
|
||||
manager.operationQueue.maxConcurrentOperationCount = 2;
|
||||
NSURL *URL = [NSURL URLWithString:t_model.content];
|
||||
|
||||
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:[NSURLRequest requestWithURL:URL] progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
|
||||
|
||||
// 存储文件夹创建
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:t_model.production_id chapter_id:t_model.chapter_id productionType:TFProductionTypeAudio]]) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:t_model.production_id chapter_id:t_model.chapter_id productionType:TFProductionTypeAudio] withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
|
||||
// 获取图片名称
|
||||
NSString *audioFileName = [TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@", [TFUtilsHelper formatStringWithInteger:t_model.production_id], [TFUtilsHelper formatStringWithInteger:t_model.chapter_id], [TFUtilsHelper formatStringWithObject:t_model.update_time]]];
|
||||
|
||||
// 图片地址
|
||||
NSString *audioFilePath = [[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:t_model.production_id chapter_id:t_model.chapter_id productionType:TFProductionTypeAudio] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", audioFileName, [TFViewHelper audioExtensionWithFormatString:[response MIMEType]]]];
|
||||
|
||||
return [NSURL fileURLWithPath:audioFilePath];
|
||||
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
|
||||
if (error) {
|
||||
// 删除出错章节文件夹
|
||||
[[WXYZ_DownloadHelper sharedManager] removeDownloadChapterFolderWithProduction_id:t_model.production_id chapter_ids:@[[TFUtilsHelper formatStringWithInteger:t_model.chapter_id]] productionType:TFProductionTypeAudio];
|
||||
[[weakSelf audioChaptersRecordDictionaryWithProduction_id:t_model.production_id] setObject:identify_fail forKey:chapterRecordKey(t_model.production_id, t_model.chapter_id)];
|
||||
[weakSelf audioRecordWriteToPlistWithProduction_id:t_model.production_id];
|
||||
|
||||
// 章节下载失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadChapterStateChangeBlock) {
|
||||
weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFail, t_model.production_id, t_model.chapter_id);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
// 下载成功 覆盖临时下载记录
|
||||
[[weakSelf audioChaptersRecordDictionaryWithProduction_id:t_model.production_id] setObject:t_model forKey:chapterRecordKey(t_model.production_id, t_model.chapter_id)];
|
||||
[weakSelf audioRecordWriteToPlistWithProduction_id:t_model.production_id];
|
||||
|
||||
// 章节下载成功
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadChapterStateChangeBlock) {
|
||||
weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFinished, t_model.production_id, t_model.chapter_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dispatch_group_leave(audio_group);
|
||||
}];
|
||||
[downloadTask resume];
|
||||
});
|
||||
}
|
||||
dispatch_group_notify(audio_group, audio_queue, ^{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
weakSelf.requesting = NO;
|
||||
if (weakSelf.requestOrderArray.count == 0) {
|
||||
|
||||
// 任务完成
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFinished, 0, @[]);
|
||||
}
|
||||
} else {
|
||||
[weakSelf downloadTaskRequest];
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (NSMutableArray *)requestOrderArray
|
||||
{
|
||||
if (!_requestOrderArray) {
|
||||
_requestOrderArray = [NSMutableArray array];
|
||||
}
|
||||
return _requestOrderArray;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *)audioChaptersRecordDictionaryWithProduction_id:(NSUInteger)production_id
|
||||
{
|
||||
return [[WXYZ_DownloadHelper sharedManager] chaptersRecordDownloadDictionaryWithProduction_id:production_id productionType:TFProductionTypeAudio modelClass:[TFProductionChapterModel class]];
|
||||
}
|
||||
|
||||
- (BOOL)audioRecordWriteToPlistWithProduction_id:(NSUInteger)production_id
|
||||
{
|
||||
return [[WXYZ_DownloadHelper sharedManager] writeToChapterPlistFileWithProduction_id:production_id productionType:TFProductionTypeAudio modelClass:[TFProductionChapterModel class]];
|
||||
}
|
||||
|
||||
@end
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// WXYZ_BBBBBBBManager.h
|
||||
// WXReader
|
||||
//
|
||||
// Created by Andrew on 2020/7/10.
|
||||
// Copyright © 2020 Andrew. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "WXYZ_DownloadHelper.h"
|
||||
#import "TFNovelDownloadTaskListModel.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface WXYZ_BookDownloadManager : NSObject <WXYZ_DownloadManagerEnumProtocol>
|
||||
|
||||
@property (nonatomic, copy) void (^downloadDeleteFinishBlock)(NSArray *success_chapter_ids, NSArray *fail_chapter);
|
||||
|
||||
// 总体任务下载回调
|
||||
@property (nonatomic, copy) void (^downloadMissionStateChangeBlock)(WXYZ_DownloadMissionState state, NSInteger production_id, TFDownloadTaskModel *downloadTaskModel, NSArray<NSNumber *> * _Nullable chapterIDArray);
|
||||
|
||||
interface_singleton
|
||||
|
||||
/*
|
||||
增
|
||||
**/
|
||||
|
||||
// 下载章节(不支持自动订阅 && 支持多章下载)
|
||||
- (void)downloadChaptersWithProductionModel:(TFProductionModel *)productionModel downloadTaskModel:(TFDownloadTaskModel *)downloadTaskModel production_id:(NSInteger)production_id start_chapter_id:(NSInteger)start_chapter_id downloadNum:(NSInteger)downloadNum;
|
||||
|
||||
/*
|
||||
删
|
||||
**/
|
||||
|
||||
// 删除本地已下载作品
|
||||
- (BOOL)removeDownloadProductionWithProduction_id:(NSInteger)production_id;
|
||||
|
||||
/*
|
||||
查
|
||||
**/
|
||||
// 获取已下载文件路径
|
||||
- (NSString *)getChapterFilePathWithChapterModel:(TFProductionChapterModel *)chapterModel;
|
||||
|
||||
// 获取章节内容
|
||||
- (NSString *)getFileContentsWithChapterModel:(TFProductionChapterModel * __nullable)chapterModel;
|
||||
|
||||
// 存储章节内容
|
||||
- (void)storingFilesWithChapterModel:(TFProductionChapterModel * __nullable)chapterModel storingCompletionHandler:(void (^)(BOOL finishStoring))completionHandler;
|
||||
|
||||
// 获取下载状态
|
||||
- (WXYZ_ProductionDownloadState)getDownloadMissionStateWithProduction_id:(NSInteger)production_id downloadTaskModel:(TFDownloadTaskModel *)downloadTaskModel;
|
||||
|
||||
// 获取某一已下载作品model
|
||||
- (TFNovelDownloadTaskListModel *)getDownloadProductionModelWithProduction_id:(NSInteger)production_id;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+470
@@ -0,0 +1,470 @@
|
||||
//
|
||||
// WXYZ_BBBBBBBManager.m
|
||||
// WXReader
|
||||
//
|
||||
// Created by Andrew on 2020/7/10.
|
||||
// Copyright © 2020 Andrew. All rights reserved.
|
||||
//
|
||||
|
||||
#import "WXYZ_BookDownloadManager.h"
|
||||
#import "TFProductionChapterModel.h"
|
||||
|
||||
// 下载总任务列表model
|
||||
#define TaskListKey @"task_list_key"
|
||||
|
||||
@interface WXYZ_BookDownloadManager ()
|
||||
|
||||
@property (nonatomic, assign) BOOL requesting;
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray *requestOrderArray;
|
||||
|
||||
@end
|
||||
|
||||
@implementation WXYZ_BookDownloadManager
|
||||
|
||||
implementation_singleton(WXYZ_BookDownloadManager)
|
||||
|
||||
/*
|
||||
增
|
||||
**/
|
||||
|
||||
// 下载多个章节
|
||||
- (void)downloadChaptersWithProductionModel:(TFProductionModel *)productionModel downloadTaskModel:(TFDownloadTaskModel *)downloadTaskModel production_id:(NSInteger)production_id start_chapter_id:(NSInteger)start_chapter_id downloadNum:(NSInteger)downloadNum
|
||||
{
|
||||
|
||||
// 作品开始下载标记
|
||||
[[WXYZ_DownloadHelper sharedManager] recordDownloadProductionWithProductionModel:productionModel productionType:TFProductionTypeNovel];
|
||||
|
||||
// 任务加入任务队列
|
||||
/*
|
||||
@{
|
||||
production_id:@[起始章节id, 下载章节数量, 下载任务对象]
|
||||
}
|
||||
*/
|
||||
[self.requestOrderArray addObject:@{[TFUtilsHelper formatStringWithInteger:production_id]:@[[TFUtilsHelper formatStringWithInteger:start_chapter_id], [TFUtilsHelper formatStringWithInteger:downloadNum], downloadTaskModel]}];
|
||||
|
||||
if (!self.requesting) {
|
||||
// 开始下载任务
|
||||
[self downloadTaskRequest];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
删
|
||||
**/
|
||||
|
||||
// 删除本地整本已下载作品
|
||||
- (BOOL)removeDownloadProductionWithProduction_id:(NSInteger)production_id
|
||||
{
|
||||
// 删除作品文件夹
|
||||
[[WXYZ_DownloadHelper sharedManager] removeDownloadProductionFolderWithProduction_id:production_id productionType:TFProductionTypeNovel];
|
||||
|
||||
[[self bookDownloadTaskDictionaryWithProduction_id:production_id] removeAllObjects];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
/*
|
||||
查
|
||||
**/
|
||||
|
||||
// 获取已下载小说文件路径
|
||||
- (NSString *)getChapterFilePathWithChapterModel:(TFProductionChapterModel *)chapterModel
|
||||
{
|
||||
// 章节图片名称
|
||||
NSString *fileName = [TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@%@", [TFUtilsHelper formatStringWithInteger:chapterModel.production_id], [TFUtilsHelper formatStringWithInteger:chapterModel.chapter_id], [TFUtilsHelper formatStringWithInteger:chapterModel.is_preview], chapterModel.update_time]];
|
||||
|
||||
NSString *filePath = [[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:chapterModel.production_id chapter_id:chapterModel.chapter_id productionType:TFProductionTypeNovel] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.txt", fileName]];
|
||||
|
||||
return filePath;
|
||||
}
|
||||
|
||||
// 获取章节内容
|
||||
- (NSString *)getFileContentsWithChapterModel:(TFProductionChapterModel *)chapterModel
|
||||
{
|
||||
// 数据不正确
|
||||
if (!chapterModel || chapterModel.production_id == 0 || chapterModel.chapter_id == 0 || !chapterModel.update_time) {
|
||||
return k_Chapter_RequstFail;
|
||||
}
|
||||
|
||||
// 本地文件地址
|
||||
NSString *filePath = [self getChapterFilePathWithChapterModel:chapterModel];
|
||||
|
||||
// 如果文件存在则返回文件内容
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
|
||||
|
||||
NSString *body = [NSString stringWithContentsOfURL:[NSURL fileURLWithPath:filePath] usedEncoding:nil error:nil];
|
||||
if (body) {
|
||||
return body;
|
||||
}
|
||||
//如果之前不能解码,现在使用GBK解码
|
||||
body = [NSString stringWithContentsOfURL:[NSURL fileURLWithPath:filePath] encoding:0x80000632 error:nil];
|
||||
if (body) {
|
||||
return body;
|
||||
}
|
||||
//再使用GB18030解码
|
||||
body = [NSString stringWithContentsOfURL:[NSURL fileURLWithPath:filePath] encoding:0x80000631 error:nil];
|
||||
if (body) {
|
||||
return body;
|
||||
} else {
|
||||
return k_Chapter_RequstFail;
|
||||
}
|
||||
} else {
|
||||
return k_Chapter_RequstFail;
|
||||
}
|
||||
}
|
||||
|
||||
// 存储章节内容
|
||||
- (void)storingFilesWithChapterModel:(TFProductionChapterModel *)chapterModel storingCompletionHandler:(void (^)(BOOL finishStoring))completionHandler
|
||||
{
|
||||
// 数据不正确
|
||||
if (!chapterModel || chapterModel.production_id == 0 || chapterModel.chapter_id == 0 || !chapterModel.update_time) {
|
||||
if (completionHandler) {
|
||||
completionHandler(NO);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 文件已存在
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:[self getChapterFilePathWithChapterModel:chapterModel]]) {
|
||||
|
||||
// 如果当前获取的是非预览章节内容,则寻找是否有预览章节文件进行删除,节省空间
|
||||
chapterModel.is_preview = 1;
|
||||
if ([self getChapterFilePathWithChapterModel:chapterModel]) {
|
||||
[[NSFileManager defaultManager] removeItemAtPath:[self getChapterFilePathWithChapterModel:chapterModel] error:nil];
|
||||
}
|
||||
|
||||
if (completionHandler) {
|
||||
completionHandler(NO);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 文件不存在则存储文件
|
||||
|
||||
// 解析标题
|
||||
NSString *chapter_title_string = @"";
|
||||
if (chapterModel.chapter_title && chapterModel.chapter_title.length > 0) {
|
||||
chapter_title_string = [NSString stringWithFormat:@"W$$X%@W$$X", chapterModel.chapter_title];
|
||||
chapter_title_string = [chapter_title_string stringByAppendingString:@"\n\n"];
|
||||
}
|
||||
|
||||
// 解析内容
|
||||
NSString *chapter_content_string = @"";
|
||||
if (chapterModel.content && chapterModel.content.length > 0) {
|
||||
chapter_content_string = chapterModel.content;
|
||||
}
|
||||
|
||||
// 文件内容
|
||||
NSString *chapter_file_content = [NSString stringWithFormat:@"%@%@",chapter_title_string, chapter_content_string];
|
||||
|
||||
if ([chapter_file_content writeToFile:[self getChapterFilePathWithChapterModel:chapterModel] atomically:NO encoding:NSUTF8StringEncoding error:nil]) {
|
||||
if (completionHandler) {
|
||||
completionHandler(YES);
|
||||
}
|
||||
} else {
|
||||
if (completionHandler) {
|
||||
completionHandler(NO);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 获取下载状态
|
||||
- (WXYZ_ProductionDownloadState)getDownloadMissionStateWithProduction_id:(NSInteger)production_id downloadTaskModel:(TFDownloadTaskModel *)downloadTaskModel
|
||||
{
|
||||
NSMutableDictionary *t_dic = [self bookDownloadTaskDictionaryWithProduction_id:production_id];
|
||||
if ([[t_dic objectForKey:downloadTaskModel.file_name] isEqual:identify_downloading]) {
|
||||
return WXYZ_ProductionDownloadStateDownloading;
|
||||
}
|
||||
|
||||
if ([[t_dic objectForKey:downloadTaskModel.file_name] isKindOfClass:[TFDownloadTaskModel class]]) {
|
||||
return WXYZ_ProductionDownloadStateDownloaded;
|
||||
}
|
||||
|
||||
TFNovelDownloadTaskListModel *taskListModel = [self getDownloadProductionModelWithProduction_id:production_id];
|
||||
if (taskListModel.task_list.count > 0) {
|
||||
for (TFDownloadTaskModel *t_taskModel in taskListModel.task_list) {
|
||||
if (downloadTaskModel.start_order >= t_taskModel.start_order && downloadTaskModel.end_order <= t_taskModel.end_order) {
|
||||
return WXYZ_ProductionDownloadStateDownloaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return WXYZ_ProductionDownloadStateNormal;
|
||||
}
|
||||
|
||||
// 获取某一已下载作品model
|
||||
- (TFNovelDownloadTaskListModel *)getDownloadProductionModelWithProduction_id:(NSInteger)production_id
|
||||
{
|
||||
TFNovelDownloadTaskListModel *taskListModel = [[TFNovelDownloadTaskListModel alloc] init];
|
||||
taskListModel.productionModel = [[WXYZ_DownloadHelper sharedManager] getDownloadProductionModelWithProduction_id:production_id productionType:TFProductionTypeNovel];
|
||||
taskListModel.task_list = [[self getDownloadProductionArrayWithProduction_id:production_id] mutableCopy];
|
||||
return taskListModel;
|
||||
}
|
||||
|
||||
// 获取某一作品的全部下载model
|
||||
- (NSArray <TFDownloadTaskModel *> *)getDownloadProductionArrayWithProduction_id:(NSInteger)production_id
|
||||
{
|
||||
NSMutableArray *t_arr = [NSMutableArray array];
|
||||
for (id taskModel in [self bookDownloadTaskDictionaryWithProduction_id:production_id].allValues) {
|
||||
if ([taskModel isKindOfClass:[TFDownloadTaskModel class]]) {
|
||||
[t_arr addObject:taskModel];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < t_arr.count; i ++) {
|
||||
TFDownloadTaskModel *taskModel = [t_arr objectAtIndex:i];
|
||||
// 是否需要合并
|
||||
BOOL isMerged = NO;
|
||||
|
||||
// 无交集
|
||||
BOOL noIntersection = YES;
|
||||
|
||||
do {
|
||||
|
||||
isMerged = NO;
|
||||
|
||||
// 遍历数组 组成队列
|
||||
NSMutableArray *array = [NSMutableArray array];
|
||||
for (NSInteger i = taskModel.start_order; i < taskModel.end_order + 3; i++) {
|
||||
[array addObject:[TFUtilsHelper formatStringWithInteger:i - 1]];
|
||||
}
|
||||
|
||||
for (int i = 0; i < t_arr.count; i ++) {
|
||||
TFDownloadTaskModel *t_task = [t_arr objectOrNilAtIndex:i];
|
||||
|
||||
if (t_task.start_order != taskModel.start_order || t_task.end_order != taskModel.end_order) {
|
||||
if ([array containsObject:[TFUtilsHelper formatStringWithInteger:t_task.start_order]]) {
|
||||
|
||||
TFDownloadTaskModel *tt_task = [[TFDownloadTaskModel alloc] init];
|
||||
tt_task.url = taskModel.url;
|
||||
tt_task.file_name = taskModel.file_name;
|
||||
tt_task.download_title = [NSString stringWithFormat:@"%@ - %@%@", [array objectOrNilAtIndex:1], [TFUtilsHelper formatStringWithInteger:t_task.end_order > taskModel.end_order?t_task.end_order:taskModel.end_order], TFLocalizedString(@"章")];
|
||||
tt_task.dateString = [TFUtilsHelper currentDateStringWithFormat:@"yyyy-MM-dd"];
|
||||
tt_task.file_size = taskModel.file_size + t_task.file_size;
|
||||
tt_task.start_order = [[array objectOrNilAtIndex:1] integerValue];
|
||||
tt_task.end_order = t_task.end_order > taskModel.end_order?t_task.end_order:taskModel.end_order;
|
||||
|
||||
[t_arr replaceObjectAtIndex:i withObject:tt_task];
|
||||
[t_arr removeObject:taskModel];
|
||||
isMerged = YES;
|
||||
noIntersection = NO;
|
||||
|
||||
} else if ([array containsObject:[TFUtilsHelper formatStringWithInteger:t_task.end_order]]) {
|
||||
TFDownloadTaskModel *tt_task = [[TFDownloadTaskModel alloc] init];
|
||||
tt_task.url = taskModel.url;
|
||||
tt_task.file_name = taskModel.file_name;
|
||||
tt_task.download_title = [NSString stringWithFormat:@"%@ - %@%@", [TFUtilsHelper formatStringWithInteger:t_task.start_order], [TFUtilsHelper formatStringWithInteger:t_task.end_order > taskModel.end_order?t_task.end_order:taskModel.end_order], TFLocalizedString(@"章")];
|
||||
tt_task.dateString = [TFUtilsHelper currentDateStringWithFormat:@"yyyy-MM-dd"];
|
||||
tt_task.file_size = taskModel.file_size + t_task.file_size;
|
||||
tt_task.start_order = t_task.start_order;
|
||||
tt_task.end_order = t_task.end_order > taskModel.end_order?t_task.end_order:taskModel.end_order;
|
||||
|
||||
[t_arr replaceObjectAtIndex:i withObject:tt_task];
|
||||
[t_arr removeObject:taskModel];
|
||||
isMerged = YES;
|
||||
noIntersection = NO;
|
||||
|
||||
}
|
||||
if (isMerged) {
|
||||
taskModel = [t_arr objectOrNilAtIndex:0];
|
||||
break;
|
||||
}
|
||||
|
||||
} else if (t_task.start_order == taskModel.start_order && t_task.end_order == taskModel.end_order) {
|
||||
[t_arr replaceObjectAtIndex:i withObject:taskModel];
|
||||
noIntersection = NO;
|
||||
}
|
||||
}
|
||||
|
||||
} while (isMerged);
|
||||
|
||||
if (noIntersection) {
|
||||
[t_arr addObject:taskModel];
|
||||
}
|
||||
}
|
||||
|
||||
return [t_arr copy];
|
||||
}
|
||||
|
||||
- (void)downloadTaskRequest
|
||||
{
|
||||
if (self.requestOrderArray.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.requesting = YES;
|
||||
|
||||
NSDictionary *orderDic = [self.requestOrderArray firstObject];
|
||||
NSInteger production_id = [[orderDic.allKeys firstObject] integerValue];
|
||||
NSString *start_chapter_id = [orderDic objectForKey:[TFUtilsHelper formatStringWithInteger:production_id]][0];
|
||||
NSString *downloadNum = [orderDic objectForKey:[TFUtilsHelper formatStringWithInteger:production_id]][1];
|
||||
TFDownloadTaskModel *taskModel = [orderDic objectForKey:[TFUtilsHelper formatStringWithInteger:production_id]][2];
|
||||
|
||||
[self.requestOrderArray removeFirstObject];
|
||||
|
||||
WS(weakSelf)
|
||||
|
||||
[TFNetworkTools POST:Book_Download_Multiple_Chapters parameters:@{@"book_id":[TFUtilsHelper formatStringWithInteger:production_id], @"chapter_id":start_chapter_id, @"num":downloadNum} model:nil success:^(BOOL isSuccess, NSDictionary * _Nullable t_model, TFNetworkRequestModel * _Nonnull requestModel) {
|
||||
if (isSuccess) {
|
||||
if (weakSelf.requestOrderArray.count == 0) {
|
||||
[TFPromptManager showPromptViewWithStatus:TFPromptStatusSuccess promptTitle:TFLocalizedString(@"已加入下载队列")];
|
||||
}
|
||||
|
||||
// 开始下载
|
||||
[[self bookDownloadTaskDictionaryWithProduction_id:production_id] setObject:identify_downloading forKey:taskModel.file_name];
|
||||
[self bookWriteToPlistWithProduction_id:production_id];
|
||||
|
||||
// 任务开始
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.downloadMissionStateChangeBlock) {
|
||||
self.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionStart, production_id, taskModel, nil);
|
||||
}
|
||||
});
|
||||
|
||||
// 下载章节合集文件
|
||||
AFURLSessionManager *manager = [[AFURLSessionManager alloc] init];
|
||||
manager.operationQueue.maxConcurrentOperationCount = 1;
|
||||
manager.completionQueue = dispatch_queue_create("com.wxyz.book_queue", NULL);
|
||||
NSURL *URL = [NSURL URLWithString:[requestModel.data objectForKey:@"file_url"]];
|
||||
|
||||
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:[NSURLRequest requestWithURL:URL] progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
|
||||
|
||||
// 创建临时存储文件
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:[[WXYZ_DownloadHelper sharedManager] getDownloadProductionFolderPathWithProduction_id:production_id productionType:TFProductionTypeNovel]]) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:[[WXYZ_DownloadHelper sharedManager] getDownloadProductionFolderPathWithProduction_id:production_id productionType:TFProductionTypeNovel] withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
|
||||
// 临时文件地址
|
||||
NSString *tempFilePath = [[[WXYZ_DownloadHelper sharedManager] getDownloadProductionFolderPathWithProduction_id:production_id productionType:TFProductionTypeNovel] stringByAppendingPathComponent:[requestModel.data objectForKey:@"file_name"]];
|
||||
|
||||
return [NSURL fileURLWithPath:tempFilePath];
|
||||
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
|
||||
weakSelf.requesting = NO;
|
||||
if (error) {
|
||||
|
||||
// 任务下载失败删除记录
|
||||
[[self bookDownloadTaskDictionaryWithProduction_id:production_id] removeObjectForKey:taskModel.file_name];
|
||||
[self bookWriteToPlistWithProduction_id:production_id];
|
||||
|
||||
// 任务下载失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, taskModel, nil);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
NSString *fileContent = [NSString stringWithContentsOfFile:filePath.path encoding:NSUTF8StringEncoding error:nil];
|
||||
if (fileContent.length > 0) {
|
||||
NSArray *chapterModelArray = [NSArray modelArrayWithClass:[TFProductionChapterModel class] json:fileContent];
|
||||
|
||||
if (chapterModelArray.count > 0) {
|
||||
for (int i = 0; i < chapterModelArray.count; i ++) {
|
||||
|
||||
TFProductionChapterModel *chapterModel = [chapterModelArray objectAtIndex:i];
|
||||
|
||||
// 文件请求成功,解析文件内容
|
||||
[self storingFilesWithChapterModel:chapterModel storingCompletionHandler:^(BOOL finishStoring) {
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
// 存储下载任务列表
|
||||
taskModel.file_size = [TFUtilsHelper getFileSize:filePath.path];
|
||||
[[self bookDownloadTaskDictionaryWithProduction_id:production_id] setObject:taskModel forKey:taskModel.file_name];
|
||||
[self bookWriteToPlistWithProduction_id:production_id];
|
||||
|
||||
// 任务下载完成
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
NSArray<NSNumber *> *t_arr = [chapterModelArray valueForKeyPath:@"chapter_id"];
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFinished, production_id, taskModel, t_arr);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
// 任务下载失败删除记录
|
||||
[[self bookDownloadTaskDictionaryWithProduction_id:production_id] removeObjectForKey:taskModel.file_name];
|
||||
[self bookWriteToPlistWithProduction_id:production_id];
|
||||
|
||||
// 任务下载失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, taskModel, nil);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 移除临时文件
|
||||
[[NSFileManager defaultManager] removeItemAtPath:filePath.path error:nil];
|
||||
}];
|
||||
[downloadTask resume];
|
||||
} else if (Compare_Json_isEqualTo(requestModel.code, 701)) {
|
||||
weakSelf.requesting = NO;
|
||||
|
||||
// 任务下载失败删除记录
|
||||
[[self bookDownloadTaskDictionaryWithProduction_id:production_id] removeObjectForKey:taskModel.file_name];
|
||||
[self bookWriteToPlistWithProduction_id:production_id];
|
||||
|
||||
// 任务下载失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionShouldPay, production_id, taskModel, nil);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
weakSelf.requesting = NO;
|
||||
|
||||
// 任务下载失败删除记录
|
||||
[[self bookDownloadTaskDictionaryWithProduction_id:production_id] removeObjectForKey:taskModel.file_name];
|
||||
[self bookWriteToPlistWithProduction_id:production_id];
|
||||
|
||||
// 任务下载失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, taskModel, nil);
|
||||
}
|
||||
});
|
||||
}
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
weakSelf.requesting = NO;
|
||||
|
||||
// 任务下载失败删除记录
|
||||
[[self bookDownloadTaskDictionaryWithProduction_id:production_id] removeObjectForKey:taskModel.file_name];
|
||||
[self bookWriteToPlistWithProduction_id:production_id];
|
||||
|
||||
// 任务下载失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, taskModel, nil);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSMutableArray *)requestOrderArray
|
||||
{
|
||||
if (!_requestOrderArray) {
|
||||
_requestOrderArray = [NSMutableArray array];
|
||||
}
|
||||
return _requestOrderArray;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *)bookDownloadTaskDictionaryWithProduction_id:(NSUInteger)production_id
|
||||
{
|
||||
return [[WXYZ_DownloadHelper sharedManager] chaptersRecordDownloadDictionaryWithProduction_id:production_id productionType:TFProductionTypeNovel modelClass:[TFDownloadTaskModel class]];
|
||||
}
|
||||
|
||||
- (BOOL)bookWriteToPlistWithProduction_id:(NSUInteger)production_id
|
||||
{
|
||||
return [[WXYZ_DownloadHelper sharedManager] writeToChapterPlistFileWithProduction_id:production_id productionType:TFProductionTypeNovel modelClass:[TFDownloadTaskModel class]];
|
||||
}
|
||||
|
||||
@end
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
//
|
||||
// WXYZ_ComicDownloadManager.h
|
||||
// WXReader
|
||||
//
|
||||
// Created by Andrew on 2020/3/29.
|
||||
// Copyright © 2020 Andrew. All rights reserved.
|
||||
//
|
||||
|
||||
#import "WXYZ_DownloadHelper.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface WXYZ_ComicDownloadManager : NSObject <WXYZ_DownloadManagerProtocol>
|
||||
|
||||
@property (nonatomic, copy) void (^downloadDeleteFinishBlock)(NSArray *success_chapter_ids, NSArray *fail_chapter);
|
||||
|
||||
// 章节下载状态改变
|
||||
@property (nonatomic, copy) void (^downloadChapterStateChangeBlock)(WXYZ_DownloadChapterState state, NSInteger production_id, NSInteger chapter_id);
|
||||
|
||||
// 总体任务下载完成
|
||||
@property (nonatomic, copy) void (^downloadMissionStateChangeBlock)(WXYZ_DownloadMissionState state, NSInteger production_id, NSArray *chapter_ids);
|
||||
|
||||
interface_singleton
|
||||
|
||||
- (NSArray *)getDownloadChapterModelArrayWithProduction_id:(NSInteger)production_id;
|
||||
|
||||
// 获取本地图片
|
||||
- (UIImage *)getDownloadLocalImageWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id image_id:(NSInteger)image_id image_update_time:(NSInteger)image_update_time;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+429
@@ -0,0 +1,429 @@
|
||||
//
|
||||
// WXYZ_ComicDownloadManager.m
|
||||
// WXReader
|
||||
//
|
||||
// Created by Andrew on 2020/3/29.
|
||||
// Copyright © 2020 Andrew. All rights reserved.
|
||||
//
|
||||
|
||||
#import "WXYZ_ComicDownloadManager.h"
|
||||
|
||||
static dispatch_group_t url_session_manager_completion_group() {
|
||||
static dispatch_group_t af_url_session_manager_completion_group;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
af_url_session_manager_completion_group = dispatch_group_create();
|
||||
});
|
||||
|
||||
return af_url_session_manager_completion_group;
|
||||
}
|
||||
|
||||
@interface WXYZ_ComicDownloadManager ()
|
||||
|
||||
@property (nonatomic, assign) BOOL requesting;
|
||||
|
||||
@property (nonatomic, strong) NSMutableArray *requestOrderArray;
|
||||
|
||||
@end
|
||||
|
||||
@implementation WXYZ_ComicDownloadManager
|
||||
|
||||
implementation_singleton(WXYZ_ComicDownloadManager)
|
||||
|
||||
/*
|
||||
增
|
||||
**/
|
||||
|
||||
// 下载章节
|
||||
- (void)downloadChapterWithProductionModel:(TFProductionModel *)productionModel production_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id
|
||||
{
|
||||
[self downloadChaptersWithProductionModel:productionModel production_id:production_id chapter_ids:@[[TFUtilsHelper formatStringWithInteger:chapter_id]]];
|
||||
}
|
||||
|
||||
// 下载多个章节
|
||||
- (void)downloadChaptersWithProductionModel:(TFProductionModel *)productionModel production_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *>*)chapter_ids
|
||||
{
|
||||
// 作品开始下载标记
|
||||
[[WXYZ_DownloadHelper sharedManager] recordDownloadProductionWithProductionModel:productionModel productionType:TFProductionTypeComic];
|
||||
|
||||
WS(weakSelf)
|
||||
[TFNetworkTools POST:Comic_Download parameters:@{@"comic_id":[TFUtilsHelper formatStringWithInteger:production_id], @"chapter_id":[chapter_ids componentsJoinedByString:@","]} model:nil success:^(BOOL isSuccess, NSDictionary * _Nullable t_model, TFNetworkRequestModel * _Nonnull requestModel) {
|
||||
if (isSuccess) {
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// 任务开始
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionStart, production_id, chapter_ids);
|
||||
}
|
||||
|
||||
|
||||
// 任务加入任务队列
|
||||
NSArray *taskArray = [t_model objectForKey:@"data"];
|
||||
if (taskArray.count > 0) {
|
||||
|
||||
for (NSDictionary *t_dic in taskArray) {
|
||||
TFProductionChapterModel *imageCollectionModel = [TFProductionChapterModel modelWithDictionary:t_dic];
|
||||
if (imageCollectionModel) {
|
||||
// 开始下载
|
||||
[[self comicChaptersRecordDictionaryWithProduction_id:imageCollectionModel.production_id] setObject:identify_downloading forKey:chapterRecordKey(imageCollectionModel.production_id, imageCollectionModel.chapter_id)];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.downloadChapterStateChangeBlock) {
|
||||
self.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadStart, imageCollectionModel.production_id, imageCollectionModel.chapter_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
[weakSelf.requestOrderArray addObject:taskArray];
|
||||
|
||||
if (!weakSelf.requesting) {
|
||||
[TFPromptManager showPromptViewWithStatus:TFPromptStatusSuccess promptTitle:TFLocalizedString(@"已加入下载列表")];
|
||||
}
|
||||
|
||||
// 开始下载任务
|
||||
[weakSelf downloadTaskRequestWithProduction_id:production_id];
|
||||
} else {
|
||||
// 任务失败
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, chapter_ids);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} else if (Compare_Json_isEqualTo(requestModel.code, 701)) { // 请求购买
|
||||
|
||||
// 任务失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionShouldPay, production_id, chapter_ids);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
[TFPromptManager showPromptViewWithStatus:TFPromptStatusError promptTitle:requestModel.msg];
|
||||
|
||||
// 任务失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, chapter_ids);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
|
||||
|
||||
// 任务失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, chapter_ids);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
/*
|
||||
删
|
||||
**/
|
||||
|
||||
// 删除本地整本已下载作品
|
||||
- (BOOL)removeDownloadProductionWithProduction_id:(NSInteger)production_id
|
||||
{
|
||||
// 删除作品文件夹
|
||||
[[WXYZ_DownloadHelper sharedManager] removeDownloadProductionFolderWithProduction_id:production_id productionType:TFProductionTypeComic];
|
||||
|
||||
// 删除缓存
|
||||
[[self comicChaptersRecordDictionaryWithProduction_id:production_id] removeAllObjects];
|
||||
|
||||
// 写入
|
||||
[self comicRecordWriteToPlistWithProduction_id:production_id];
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
// 删除本地多个已下载章节
|
||||
- (void)removeDownloadChaptersWithProduction_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *> *)chapter_ids
|
||||
{
|
||||
if (chapter_ids.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 删除文件夹
|
||||
[[WXYZ_DownloadHelper sharedManager] removeDownloadChapterFolderWithProduction_id:production_id chapter_ids:chapter_ids productionType:TFProductionTypeComic];
|
||||
|
||||
// 删除下载记录
|
||||
NSMutableDictionary *t_dic = [self comicChaptersRecordDictionaryWithProduction_id:production_id];
|
||||
|
||||
NSMutableArray *t_delete_arr = [NSMutableArray array];
|
||||
for (NSString *chapter_id in chapter_ids) {
|
||||
[t_delete_arr addObject:chapterRecordKey(production_id, [chapter_id integerValue])];
|
||||
}
|
||||
|
||||
[t_dic removeObjectsForKeys:t_delete_arr];
|
||||
|
||||
// 如果全部章节已经删除,则删除整体作品文件夹
|
||||
if ([self getDownloadChapterCountWithProduction_id:production_id] == 0) {
|
||||
[self removeDownloadProductionWithProduction_id:production_id];
|
||||
} else {
|
||||
[self comicRecordWriteToPlistWithProduction_id:production_id];
|
||||
}
|
||||
|
||||
// 删除回调
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.downloadDeleteFinishBlock) {
|
||||
self.downloadDeleteFinishBlock(chapter_ids, @[]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
查
|
||||
**/
|
||||
|
||||
// 获取下载章节数
|
||||
- (NSInteger)getDownloadChapterCountWithProduction_id:(NSInteger)production_id
|
||||
{
|
||||
return [[WXYZ_DownloadHelper sharedManager] getDownloadChapterCountWithProduction_id:production_id productionType:TFProductionTypeComic];
|
||||
}
|
||||
|
||||
// 获取全部已下载章节model
|
||||
- (NSArray *)getDownloadChapterModelArrayWithProduction_id:(NSInteger)production_id
|
||||
{
|
||||
NSMutableDictionary *t_dic = [self comicChaptersRecordDictionaryWithProduction_id:production_id];
|
||||
|
||||
NSMutableArray *t_arr = [NSMutableArray array];
|
||||
for (id value in t_dic.allValues) {
|
||||
if ([value isKindOfClass:[TFProductionChapterModel class]]) {
|
||||
[t_arr addObject:value];
|
||||
}
|
||||
}
|
||||
return [t_arr copy];
|
||||
}
|
||||
|
||||
// 获取已下载章节model
|
||||
- (id)getDownloadChapterModelWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id
|
||||
{
|
||||
NSMutableDictionary *t_dic = [self comicChaptersRecordDictionaryWithProduction_id:production_id];
|
||||
|
||||
id value = [t_dic objectForKey:chapterRecordKey(production_id, chapter_id)];
|
||||
|
||||
if ([value isKindOfClass:[TFProductionChapterModel class]]) {
|
||||
return value;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
// 获取下载状态
|
||||
- (WXYZ_ProductionDownloadState)getChapterDownloadStateWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id
|
||||
{
|
||||
NSMutableDictionary *t_dic = [self comicChaptersRecordDictionaryWithProduction_id:production_id];
|
||||
if ([[t_dic objectForKey:chapterRecordKey(production_id, chapter_id)] isEqual:identify_downloading]) {
|
||||
return WXYZ_ProductionDownloadStateDownloading;
|
||||
}
|
||||
|
||||
if ([[t_dic objectForKey:chapterRecordKey(production_id, chapter_id)] isEqual:identify_fail]) {
|
||||
return WXYZ_ProductionDownloadStateFail;
|
||||
}
|
||||
|
||||
if ([[t_dic objectForKey:chapterRecordKey(production_id, chapter_id)] isKindOfClass:[TFProductionChapterModel class]]) {
|
||||
return WXYZ_ProductionDownloadStateDownloaded;
|
||||
}
|
||||
|
||||
return WXYZ_ProductionDownloadStateNormal;
|
||||
}
|
||||
|
||||
|
||||
// 作品章节是否下载
|
||||
- (BOOL)isChapterDownloadedWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id
|
||||
{
|
||||
return [[WXYZ_DownloadHelper sharedManager] isChapterDownloadedWithProduction_id:production_id chapter_id:chapter_id productionType:TFProductionTypeComic];
|
||||
}
|
||||
|
||||
- (UIImage *)getDownloadLocalImageWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id image_id:(NSInteger)image_id image_update_time:(NSInteger)image_update_time
|
||||
{
|
||||
UIImage *t_image = [UIImage imageWithContentsOfFile:[self chapterImageFilePathWithProduction_id:production_id chapter_id:chapter_id image_id:image_id image_update_time:image_update_time]];
|
||||
if (!t_image) {
|
||||
return nil;
|
||||
}
|
||||
return t_image;
|
||||
}
|
||||
|
||||
- (NSString *)chapterImageFilePathWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id image_id:(NSInteger)image_id image_update_time:(NSInteger)image_update_time
|
||||
{
|
||||
// 章节图片名称
|
||||
NSString *imageFileName = [TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@%@", [TFUtilsHelper formatStringWithInteger:production_id], [TFUtilsHelper formatStringWithInteger:chapter_id], [TFUtilsHelper formatStringWithInteger:image_id], [TFUtilsHelper formatStringWithInteger:image_update_time]]];
|
||||
|
||||
NSString *imageFilePath = @"";
|
||||
NSArray *extensionArr = @[@"jpeg", @"png", @"gif", @"tiff", @"webp"];
|
||||
for (NSString *extension in extensionArr) {
|
||||
imageFilePath = [[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:production_id chapter_id:chapter_id productionType:TFProductionTypeComic] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageFileName, extension]];
|
||||
if (imageFilePath && imageFilePath.length > 0 && [[NSFileManager defaultManager] fileExistsAtPath:imageFilePath]) {
|
||||
return imageFilePath;
|
||||
}
|
||||
}
|
||||
|
||||
return imageFilePath;
|
||||
}
|
||||
|
||||
- (void)downloadTaskRequestWithProduction_id:(NSInteger)production_id
|
||||
{
|
||||
if (self.requestOrderArray.count == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.requesting) {
|
||||
return;
|
||||
}
|
||||
self.requesting = YES;
|
||||
|
||||
NSArray *taskArray = [self.requestOrderArray firstObject];
|
||||
[self.requestOrderArray removeFirstObject];
|
||||
|
||||
WS(weakSelf)
|
||||
dispatch_group_async(url_session_manager_completion_group(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
// 记录出错章节
|
||||
NSMutableArray __block *errorChapter = [NSMutableArray array];
|
||||
|
||||
dispatch_semaphore_t collection_semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
// 记录章节model内容
|
||||
NSMutableArray *t_chapterModelArray = [NSMutableArray array];
|
||||
|
||||
for (NSDictionary *t_dic in taskArray) {
|
||||
dispatch_queue_t image_queue = dispatch_queue_create("wxyz_image_queue", DISPATCH_QUEUE_CONCURRENT);
|
||||
dispatch_group_t image_group = dispatch_group_create();
|
||||
|
||||
TFProductionChapterModel *imageCollectionModel = [TFProductionChapterModel modelWithDictionary:t_dic];
|
||||
|
||||
if (!imageCollectionModel) {
|
||||
|
||||
// 单个章节下载失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadChapterStateChangeBlock) {
|
||||
weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFail, imageCollectionModel.production_id, imageCollectionModel.chapter_id);
|
||||
}
|
||||
});
|
||||
continue;
|
||||
}
|
||||
[t_chapterModelArray addObject:imageCollectionModel];
|
||||
|
||||
// 解析任务 下载一话内的图片组
|
||||
for (TFImageListModel *imageModel in imageCollectionModel.image_list) {
|
||||
dispatch_group_async(image_group, image_queue, ^{
|
||||
|
||||
dispatch_group_enter(image_group);
|
||||
|
||||
// 创建图片下载器
|
||||
AFURLSessionManager *manager = [[AFURLSessionManager alloc] init];
|
||||
manager.operationQueue.maxConcurrentOperationCount = 2;
|
||||
NSURL *URL = [NSURL URLWithString:imageModel.image];
|
||||
|
||||
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:[NSURLRequest requestWithURL:URL] progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
|
||||
|
||||
// 存储文件夹创建
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:imageCollectionModel.production_id chapter_id:imageCollectionModel.chapter_id productionType:TFProductionTypeComic]]) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:imageCollectionModel.production_id chapter_id:imageCollectionModel.chapter_id productionType:TFProductionTypeComic] withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
|
||||
// 获取图片名称
|
||||
NSString *imageFileName = [TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@%@", [TFUtilsHelper formatStringWithInteger:imageCollectionModel.production_id], [TFUtilsHelper formatStringWithInteger:imageCollectionModel.chapter_id], [TFUtilsHelper formatStringWithInteger:imageModel.image_id], [TFUtilsHelper formatStringWithInteger:imageModel.image_update_time]]];
|
||||
|
||||
// 图片地址
|
||||
NSString *imageFilePath = [[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:imageCollectionModel.production_id chapter_id:imageCollectionModel.chapter_id productionType:TFProductionTypeComic] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageFileName, [TFViewHelper imageExtensionWithFormatString:[response MIMEType]]]];
|
||||
|
||||
return [NSURL fileURLWithPath:imageFilePath];
|
||||
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
|
||||
// 如果某一张出错就取消下载,删除该章节文件夹
|
||||
if (error) {
|
||||
[errorChapter addObject:[TFUtilsHelper formatStringWithInteger:imageCollectionModel.chapter_id]];
|
||||
}
|
||||
dispatch_group_leave(image_group);
|
||||
}];
|
||||
[downloadTask resume];
|
||||
});
|
||||
}
|
||||
dispatch_group_notify(image_group, image_queue, ^{
|
||||
|
||||
// 删除图片出错章节
|
||||
if (errorChapter.count > 0) {
|
||||
// 删除出错章节文件夹
|
||||
[[WXYZ_DownloadHelper sharedManager] removeDownloadChapterFolderWithProduction_id:imageCollectionModel.production_id chapter_ids:errorChapter productionType:TFProductionTypeComic];
|
||||
[[weakSelf comicChaptersRecordDictionaryWithProduction_id:imageCollectionModel.production_id] setObject:identify_fail forKey:chapterRecordKey(imageCollectionModel.production_id, imageCollectionModel.chapter_id)];
|
||||
[weakSelf comicRecordWriteToPlistWithProduction_id:imageCollectionModel.production_id];
|
||||
|
||||
// 单个章节下载失败
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadChapterStateChangeBlock) {
|
||||
weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFail, imageCollectionModel.production_id, imageCollectionModel.chapter_id);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
// 下载成功 覆盖临时下载记录
|
||||
[[weakSelf comicChaptersRecordDictionaryWithProduction_id:imageCollectionModel.production_id] setObject:imageCollectionModel forKey:chapterRecordKey(imageCollectionModel.production_id, imageCollectionModel.chapter_id)];
|
||||
[weakSelf comicRecordWriteToPlistWithProduction_id:imageCollectionModel.production_id];
|
||||
|
||||
// 单个章节下载完成
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (weakSelf.downloadChapterStateChangeBlock) {
|
||||
weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFinished, imageCollectionModel.production_id, imageCollectionModel.chapter_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
dispatch_semaphore_signal(collection_semaphore);
|
||||
});
|
||||
|
||||
dispatch_semaphore_wait(collection_semaphore, DISPATCH_TIME_FOREVER);
|
||||
}
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
weakSelf.requesting = NO;
|
||||
if (weakSelf.requestOrderArray.count == 0) {
|
||||
|
||||
// 替换已下载记录章节目录内容
|
||||
TFProductionModel *t_productionModel = [[WXYZ_DownloadHelper sharedManager] getDownloadProductionModelWithProduction_id:production_id productionType:TFProductionTypeComic];
|
||||
NSMutableArray *t_chapterList = [t_productionModel.chapter_list mutableCopy];
|
||||
for (int i = 0; i < t_chapterList.count; i++) {
|
||||
TFProductionChapterModel *t_chapterModel = [t_chapterList objectAtIndex:i];
|
||||
for (TFProductionChapterModel *tt_chapterModel in t_chapterModelArray) {
|
||||
if (tt_chapterModel.chapter_id == t_chapterModel.chapter_id) {
|
||||
[t_chapterList replaceObjectAtIndex:i withObject:tt_chapterModel];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
t_productionModel.chapter_list = [t_chapterList copy];
|
||||
[[WXYZ_DownloadHelper sharedManager] recordDownloadProductionWithProductionModel:t_productionModel productionType:TFProductionTypeComic];
|
||||
|
||||
// 任务完成
|
||||
if (weakSelf.downloadMissionStateChangeBlock) {
|
||||
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFinished, 0, @[]);
|
||||
}
|
||||
} else {
|
||||
[weakSelf downloadTaskRequestWithProduction_id:production_id];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (NSMutableArray *)requestOrderArray
|
||||
{
|
||||
if (!_requestOrderArray) {
|
||||
_requestOrderArray = [NSMutableArray array];
|
||||
}
|
||||
return _requestOrderArray;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary *)comicChaptersRecordDictionaryWithProduction_id:(NSUInteger)production_id
|
||||
{
|
||||
return [[WXYZ_DownloadHelper sharedManager] chaptersRecordDownloadDictionaryWithProduction_id:production_id productionType:TFProductionTypeComic modelClass:[TFProductionChapterModel class]];
|
||||
}
|
||||
|
||||
- (BOOL)comicRecordWriteToPlistWithProduction_id:(NSUInteger)production_id
|
||||
{
|
||||
return [[WXYZ_DownloadHelper sharedManager] writeToChapterPlistFileWithProduction_id:production_id productionType:TFProductionTypeComic modelClass:[TFProductionChapterModel class]];
|
||||
}
|
||||
|
||||
@end
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// WXYZ_DownloadHelper.h
|
||||
// WXReader
|
||||
//
|
||||
// Created by Andrew on 2020/4/1.
|
||||
// Copyright © 2020 Andrew. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "WXYZ_DownloadManagerProtocol.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
// 章节记录文件key
|
||||
#define chapterRecordKey(production_id, chapter_id) [TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@", [TFUtilsHelper formatStringWithInteger:production_id], [TFUtilsHelper formatStringWithInteger:chapter_id]]]
|
||||
|
||||
|
||||
@interface WXYZ_DownloadHelper : NSObject
|
||||
|
||||
interface_singleton
|
||||
|
||||
/*
|
||||
增
|
||||
**/
|
||||
|
||||
// 作品下载记录
|
||||
- (void)recordDownloadProductionWithProductionModel:(TFProductionModel *)productionModel productionType:(TFProductionType)productionType;
|
||||
|
||||
/*
|
||||
删
|
||||
**/
|
||||
|
||||
// 删除作品文件夹
|
||||
- (void)removeDownloadProductionFolderWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType;
|
||||
|
||||
// 删除章节文件夹
|
||||
- (BOOL)removeDownloadChapterFolderWithProduction_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *>*)chapter_ids productionType:(TFProductionType)productionType;
|
||||
/*
|
||||
查
|
||||
**/
|
||||
|
||||
// 作品章节是否下载
|
||||
- (BOOL)isChapterDownloadedWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id productionType:(TFProductionType)productionType;
|
||||
|
||||
// 下载作品文件夹路径
|
||||
- (NSString *)getDownloadProductionFolderPathWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType;
|
||||
|
||||
// 下载章节文件夹路径
|
||||
- (NSString *)getDownloadChapterFolderPathWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id productionType:(TFProductionType)productionType;
|
||||
|
||||
// 下载作品记录文件路径
|
||||
- (NSString *)getDownloadProductionRecordPlistFilePathWithProductionType:(TFProductionType)productionType;
|
||||
|
||||
// 获取下载章节数
|
||||
- (NSInteger)getDownloadChapterCountWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType;
|
||||
|
||||
// 获取类别下的所有下载作品model
|
||||
- (NSArray <TFProductionModel *> *)getDownloadProductionArrayWithProductionType:(TFProductionType)productionType;
|
||||
|
||||
// 获取某一已下载作品model
|
||||
- (TFProductionModel *)getDownloadProductionModelWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType;
|
||||
|
||||
// 章节记录缓存变量
|
||||
- (NSMutableDictionary *)chaptersRecordDownloadDictionaryWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType modelClass:(__nullable Class)modelClass;
|
||||
|
||||
// 写入章节记录文件
|
||||
- (BOOL)writeToChapterPlistFileWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType modelClass:(Class)modelClass;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+376
@@ -0,0 +1,376 @@
|
||||
//
|
||||
// WXYZ_DownloadHelper.m
|
||||
// WXReader
|
||||
//
|
||||
// Created by Andrew on 2020/4/1.
|
||||
// Copyright © 2020 Andrew. All rights reserved.
|
||||
//
|
||||
|
||||
/* 下载缓存结构示意
|
||||
WXYZ_DownloadFileFolder ━┳━ BookDownloadFileFolder ━┳━ WXYZ_DownloadProductionRecordFile.plist
|
||||
┃ ┃
|
||||
┃ ┃
|
||||
┃ ┣━ 作品文件夹(production_id) ━┳━ WXYZ_DownloadChapterRecordFile.plist
|
||||
┃ ┃ ┃
|
||||
┃ ┃ ┃
|
||||
┃ ┃ ┣━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3
|
||||
┃ ┃ ┃
|
||||
┃ ┃ ┃
|
||||
┃ ┃ ┗━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3
|
||||
┃ ┃
|
||||
┃ ┗━ 作品文件夹(production_id)
|
||||
┃
|
||||
┃
|
||||
┣━ ComicDownloadFileFolder ━┳━ WXYZ_DownloadProductionRecordFile.plist
|
||||
┃ ┃
|
||||
┃ ┃
|
||||
┃ ┣━ 作品文件夹(production_id) ━┳━ WXYZ_DownloadChapterRecordFile.plist
|
||||
┃ ┃ ┃
|
||||
┃ ┃ ┃
|
||||
┃ ┃ ┣━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3
|
||||
┃ ┃ ┃
|
||||
┃ ┃ ┃
|
||||
┃ ┃ ┗━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3
|
||||
┃ ┃
|
||||
┃ ┗━ 作品文件夹(production_id)
|
||||
┃
|
||||
┗━ AudioDownloadFileFolder ━┳━ WXYZ_DownloadProductionRecordFile.plist
|
||||
┃
|
||||
┃
|
||||
┣━ 作品文件夹(production_id) ━┳━ WXYZ_DownloadChapterRecordFile.plist
|
||||
┃ ┃
|
||||
┃ ┃
|
||||
┃ ┣━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3
|
||||
┃ ┃
|
||||
┃ ┃
|
||||
┃ ┗━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3
|
||||
┃
|
||||
┗━ 作品文件夹(production_id)
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#import "WXYZ_DownloadHelper.h"
|
||||
|
||||
@implementation WXYZ_DownloadHelper
|
||||
|
||||
implementation_singleton(WXYZ_DownloadHelper)
|
||||
|
||||
// 作品下载记录
|
||||
- (void)recordDownloadProductionWithProductionModel:(TFProductionModel *)productionModel productionType:(TFProductionType)productionType
|
||||
{
|
||||
if (!productionModel) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray *t_arr = [self productionRecordDownloadArrayWithProductionType:productionType];
|
||||
for (TFProductionModel *t_model in t_arr) {
|
||||
if (t_model.production_id == productionModel.production_id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[[self productionRecordDownloadArrayWithProductionType:productionType] addObject:productionModel];
|
||||
[self writeToPlistFileWithProductionType:productionType];
|
||||
}
|
||||
|
||||
// 删除作品下载记录
|
||||
- (void)removeRecordDownloadProductionWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType
|
||||
{
|
||||
NSMutableArray *t_arr = [[self productionRecordDownloadArrayWithProductionType:productionType] mutableCopy];
|
||||
for (TFProductionModel *t_model in t_arr) {
|
||||
if (t_model.production_id == production_id) {
|
||||
[[self productionRecordDownloadArrayWithProductionType:productionType] removeObject:t_model];
|
||||
[self writeToPlistFileWithProductionType:productionType];
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除章节下载记录(返回是否成功,如果成功那么需要在对应的downloadManager中,重置记录变量,从本地重新获取)
|
||||
- (BOOL)removeRecordDownloadChapterWithProduction_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *>*)chapter_ids productionType:(TFProductionType)productionType
|
||||
{
|
||||
NSMutableDictionary *localCacheDic = [NSMutableDictionary dictionaryWithContentsOfFile:[[WXYZ_DownloadHelper sharedManager] getDownloadChapterRecordPlistFilePathWithProduction_id:production_id productionType:productionType]];
|
||||
for (NSString *chapter_id in chapter_ids) {
|
||||
[localCacheDic removeObjectForKey:chapterRecordKey(production_id, [chapter_id integerValue])];
|
||||
}
|
||||
|
||||
NSMutableDictionary *save_dic = [NSMutableDictionary dictionary];
|
||||
for (NSString *key in localCacheDic.allKeys) {
|
||||
|
||||
id value = [localCacheDic objectForKey:key];
|
||||
|
||||
if ([value isKindOfClass:[NSClassFromString(@"WXYZ_ComicReaderModel") class]]) {
|
||||
value = [value modelToJSONString];
|
||||
}
|
||||
[save_dic setObject:value forKey:key];
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
if (![save_dic writeToFile:[self getDownloadChapterRecordPlistFilePathWithProduction_id:production_id productionType:productionType] atomically:NO]) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
// 删除作品文件夹
|
||||
- (void)removeDownloadProductionFolderWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType
|
||||
{
|
||||
// 删除plist文件记录
|
||||
[self removeRecordDownloadProductionWithProduction_id:production_id productionType:productionType];
|
||||
|
||||
// 删除对应作品整体文件夹
|
||||
[[NSFileManager defaultManager] removeItemAtPath:[self getDownloadProductionFolderPathWithProduction_id:production_id productionType:productionType] error:nil];
|
||||
}
|
||||
|
||||
// 删除章节文件夹
|
||||
- (BOOL)removeDownloadChapterFolderWithProduction_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *>*)chapter_ids productionType:(TFProductionType)productionType
|
||||
{
|
||||
for (NSString *chapter_id in chapter_ids) {
|
||||
if ([[NSFileManager defaultManager] fileExistsAtPath:[self getDownloadChapterFolderPathWithProduction_id:production_id chapter_id:[chapter_id integerValue] productionType:productionType]]) {
|
||||
[[NSFileManager defaultManager] removeItemAtPath:[self getDownloadChapterFolderPathWithProduction_id:production_id chapter_id:[chapter_id integerValue] productionType:productionType] error:nil];
|
||||
}
|
||||
}
|
||||
|
||||
// 删除章节plist文件记录
|
||||
return [self removeRecordDownloadChapterWithProduction_id:production_id chapter_ids:chapter_ids productionType:productionType];
|
||||
}
|
||||
|
||||
// 作品章节是否下载
|
||||
- (BOOL)isChapterDownloadedWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id productionType:(TFProductionType)productionType
|
||||
{
|
||||
if ([[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self getDownloadChapterFolderPathWithProduction_id:production_id chapter_id:chapter_id productionType:productionType] error:nil].count > 0) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
// 获取下载章节数
|
||||
- (NSInteger)getDownloadChapterCountWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType
|
||||
{
|
||||
// 存在已下载章节内容文件夹数量
|
||||
CGFloat chapterDownloadNumber = 0;
|
||||
|
||||
// 获取作品下全部章节文件夹名称
|
||||
NSArray <NSString *>*chapterFolderNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self getDownloadProductionFolderPathWithProduction_id:production_id productionType:productionType] error:nil];
|
||||
|
||||
for (NSString *folderName in chapterFolderNames) {
|
||||
NSString *chapterFloderPath = [[self getDownloadProductionFolderPathWithProduction_id:production_id productionType:productionType] stringByAppendingPathComponent:folderName];
|
||||
|
||||
BOOL isDirectory = NO;
|
||||
[[NSFileManager defaultManager] fileExistsAtPath:chapterFloderPath isDirectory:&isDirectory];
|
||||
if (isDirectory && [[NSFileManager defaultManager] contentsOfDirectoryAtPath:chapterFloderPath error:nil].count > 0) {
|
||||
chapterDownloadNumber ++;
|
||||
}
|
||||
}
|
||||
|
||||
return chapterDownloadNumber;
|
||||
}
|
||||
|
||||
// 获取类别下的所有下载作品
|
||||
- (NSArray <TFProductionModel *> *)getDownloadProductionArrayWithProductionType:(TFProductionType)productionType
|
||||
{
|
||||
return [self productionRecordDownloadArrayWithProductionType:productionType];
|
||||
}
|
||||
|
||||
- (TFProductionModel *)getDownloadProductionModelWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType
|
||||
{
|
||||
for (TFProductionModel *t_model in [self productionRecordDownloadArrayWithProductionType:productionType]) {
|
||||
if (t_model.production_id == production_id) {
|
||||
return t_model;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
// 主文件夹路径
|
||||
- (NSString *)getDownloadRootFolderPathWithProductionType:(TFProductionType)productionType
|
||||
{
|
||||
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectOrNilAtIndex:0];
|
||||
|
||||
// 主目录文件夹
|
||||
NSString *rootFolderPath = [documentPath stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:@"WXYZ_DownloadFileFolder"]];
|
||||
|
||||
// 创建章节文件夹
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:rootFolderPath]) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:rootFolderPath withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
|
||||
// 作品类别文件夹
|
||||
NSString *typeFolderPath = @"";
|
||||
switch (productionType) {
|
||||
case TFProductionTypeNovel: // 存储全部下载书籍
|
||||
typeFolderPath = [rootFolderPath stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:@"BookDownloadFileFolder"]];
|
||||
break;
|
||||
case TFProductionTypeComic: // 存储全部下载漫画
|
||||
typeFolderPath = [rootFolderPath stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:@"ComicDownloadFileFolder"]];
|
||||
break;
|
||||
case TFProductionTypeAudio: // 存储全部下载听书
|
||||
typeFolderPath = [rootFolderPath stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:@"AudioDownloadFileFolder"]];
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// 创建章节文件夹
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:typeFolderPath]) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:typeFolderPath withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
|
||||
return typeFolderPath;
|
||||
}
|
||||
|
||||
// 下载作品文件夹
|
||||
- (NSString *)getDownloadProductionFolderPathWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType
|
||||
{
|
||||
NSString *productionFolderPath = [[self getDownloadRootFolderPathWithProductionType:productionType] stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@", [TFUtilsHelper formatStringWithInteger:productionType], [TFUtilsHelper formatStringWithInteger:production_id]]]];
|
||||
// 创建章节文件夹
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:productionFolderPath] && production_id != 0) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:productionFolderPath withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
|
||||
return productionFolderPath;
|
||||
}
|
||||
|
||||
// 下载章节文件夹
|
||||
- (NSString *)getDownloadChapterFolderPathWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id productionType:(TFProductionType)productionType
|
||||
{
|
||||
NSString *chapterFolderPath = [[self getDownloadProductionFolderPathWithProduction_id:production_id productionType:productionType] stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@", [TFUtilsHelper formatStringWithInteger:productionType], [TFUtilsHelper formatStringWithInteger:production_id], [TFUtilsHelper formatStringWithInteger:chapter_id]]]];
|
||||
|
||||
// 创建章节文件夹
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:chapterFolderPath] && production_id != 0) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:chapterFolderPath withIntermediateDirectories:YES attributes:nil error:nil];
|
||||
}
|
||||
|
||||
return chapterFolderPath;
|
||||
}
|
||||
|
||||
// 下载作品记录文件路径
|
||||
- (NSString *)getDownloadProductionRecordPlistFilePathWithProductionType:(TFProductionType)productionType
|
||||
{
|
||||
NSString *productionRecordFilePath = [[self getDownloadRootFolderPathWithProductionType:productionType] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", [TFUtilsHelper stringToMD5:@"WXYZ_DownloadProductionRecordFile"]]];
|
||||
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:productionRecordFilePath]) {
|
||||
[@[] writeToFile:productionRecordFilePath atomically:NO];
|
||||
}
|
||||
|
||||
return productionRecordFilePath;
|
||||
}
|
||||
|
||||
// 下载章节记录文件路径
|
||||
- (NSString *)getDownloadChapterRecordPlistFilePathWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType
|
||||
{
|
||||
// 记录下载状态plist文件地址
|
||||
NSString *chapterRecordFilePath = [[self getDownloadProductionFolderPathWithProduction_id:production_id productionType:productionType] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", [TFUtilsHelper stringToMD5:@"WXYZ_DownloadChapterRecordFile"]]];
|
||||
|
||||
if (![[NSFileManager defaultManager] fileExistsAtPath:chapterRecordFilePath]) {
|
||||
[@{} writeToFile:chapterRecordFilePath atomically:NO];
|
||||
}
|
||||
|
||||
return chapterRecordFilePath;
|
||||
}
|
||||
|
||||
// 作品记录缓存变量
|
||||
static NSMutableDictionary *_productionsRecordDictionary;
|
||||
- (NSMutableArray *)productionRecordDownloadArrayWithProductionType:(TFProductionType)productionType;
|
||||
{
|
||||
if (!_productionsRecordDictionary) {
|
||||
// 此全局临时变量的作用是记录不同作品的下载记录,减少了文件的读写,增加访问效率
|
||||
_productionsRecordDictionary = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
NSMutableArray *t_arr = [_productionsRecordDictionary objectForKey:[NSString stringWithFormat:@"%@", [TFUtilsHelper formatStringWithInteger:productionType]]];
|
||||
if (!t_arr) {
|
||||
|
||||
NSMutableArray *localArr = [NSMutableArray arrayWithContentsOfFile:[self getDownloadProductionRecordPlistFilePathWithProductionType:productionType]];
|
||||
|
||||
t_arr = [NSMutableArray array];
|
||||
|
||||
for (NSString *json in localArr) {
|
||||
[t_arr addObject:[TFProductionModel modelWithJSON:json]];
|
||||
}
|
||||
|
||||
[_productionsRecordDictionary setObject:t_arr forKey:[NSString stringWithFormat:@"%@", [TFUtilsHelper formatStringWithInteger:productionType]]];
|
||||
}
|
||||
|
||||
return t_arr;
|
||||
}
|
||||
|
||||
// 写入作品记录文件
|
||||
- (BOOL)writeToPlistFileWithProductionType:(TFProductionType)productionType;
|
||||
{
|
||||
NSMutableArray *t_downloadArr = [self productionRecordDownloadArrayWithProductionType:productionType];
|
||||
|
||||
NSMutableArray *saveArr = [NSMutableArray array];
|
||||
|
||||
for (TFProductionModel *t_model in t_downloadArr) {
|
||||
[saveArr addObject:[t_model modelToJSONString]];
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
if (![saveArr writeToFile:[self getDownloadProductionRecordPlistFilePathWithProductionType:productionType] atomically:NO]) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
// 章节记录缓存变量
|
||||
static NSMutableDictionary *_chaptersRecordDictionary;
|
||||
- (NSMutableDictionary *)chaptersRecordDownloadDictionaryWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType modelClass:(Class)modelClass
|
||||
{
|
||||
if (!_chaptersRecordDictionary) {
|
||||
// 此全局临时变量的作用是记录不同作品的下载记录,减少了文件的读写,增加访问效率
|
||||
_chaptersRecordDictionary = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
NSMutableDictionary *t_dic = [_chaptersRecordDictionary objectForKey:[NSString stringWithFormat:@"%@", [TFUtilsHelper formatStringWithInteger:production_id]]];
|
||||
if (!t_dic || t_dic.count == 0) {
|
||||
|
||||
NSMutableDictionary *localDic = [NSMutableDictionary dictionaryWithContentsOfFile:[self getDownloadChapterRecordPlistFilePathWithProduction_id:production_id productionType:productionType]];
|
||||
|
||||
t_dic = [NSMutableDictionary dictionary];
|
||||
for (NSString *key in localDic.allKeys) {
|
||||
id value = [localDic objectForKey:key];
|
||||
if ([value isKindOfClass:[NSDictionary class]]) {
|
||||
[t_dic setObject:value forKey:key];
|
||||
} else if ([value isEqualToString:identify_fail]) {
|
||||
[t_dic setObject:value forKey:key];
|
||||
} else if (![value isEqual:identify_downloading] && value) {
|
||||
[t_dic setObject:[modelClass modelWithJSON:value] forKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
[_chaptersRecordDictionary setObject:t_dic forKey:[NSString stringWithFormat:@"%@", [TFUtilsHelper formatStringWithInteger:production_id]]];
|
||||
}
|
||||
|
||||
return t_dic;
|
||||
}
|
||||
|
||||
// 写入章节记录文件
|
||||
- (BOOL)writeToChapterPlistFileWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType modelClass:(Class)modelClass
|
||||
{
|
||||
NSMutableDictionary *t_downloadDic = [self chaptersRecordDownloadDictionaryWithProduction_id:production_id productionType:productionType modelClass:modelClass];
|
||||
if (t_downloadDic.count == 0) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSMutableDictionary *save_dic = [NSMutableDictionary dictionary];
|
||||
for (NSString *key in t_downloadDic.allKeys) {
|
||||
|
||||
id value = [t_downloadDic objectForKey:key];
|
||||
|
||||
if ([value isKindOfClass:[modelClass class]]) {
|
||||
value = [value modelToJSONString];
|
||||
}
|
||||
[save_dic setObject:value forKey:key];
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
if (![save_dic writeToFile:[self getDownloadChapterRecordPlistFilePathWithProduction_id:production_id productionType:productionType] atomically:NO]) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// WXYZ_DownloadManagerEnumProtocol.h
|
||||
// WXReader
|
||||
//
|
||||
// Created by Andrew on 2020/7/13.
|
||||
// Copyright © 2020 Andrew. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NS_ENUM(NSUInteger, WXYZ_DownloadChapterState) {
|
||||
WXYZ_DownloadStateChapterDownloadNormal, // 章节下载未开始
|
||||
WXYZ_DownloadStateChapterDownloadStart, // 章节下载开始
|
||||
WXYZ_DownloadStateChapterDownloadFinished, // 章节下载完成
|
||||
WXYZ_DownloadStateChapterDownloadFail // 章节下载失败
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, WXYZ_DownloadMissionState) {
|
||||
WXYZ_DownloadStateMissionShouldPay, // 任务失败需要支付
|
||||
WXYZ_DownloadStateMissionNormal, // 任务未开始
|
||||
WXYZ_DownloadStateMissionStart, // 任务开始
|
||||
WXYZ_DownloadStateMissionFinished, // 任务完成
|
||||
WXYZ_DownloadStateMissionFail // 任务失败
|
||||
};
|
||||
|
||||
typedef NS_ENUM(NSUInteger, WXYZ_ProductionDownloadState) {
|
||||
WXYZ_ProductionDownloadStateNormal = 0, // 普通状态
|
||||
WXYZ_ProductionDownloadStateDownloading = 1, // 下载中
|
||||
WXYZ_ProductionDownloadStateDownloaded = 2, // 已下载
|
||||
WXYZ_ProductionDownloadStateFail = 3, // 失败
|
||||
WXYZ_ProductionDownloadStateSelected = 4 // 选中
|
||||
};
|
||||
|
||||
#define identify_downloading @"id_downloading"
|
||||
|
||||
#define identify_fail @"id_fail"
|
||||
|
||||
@protocol WXYZ_DownloadManagerEnumProtocol <NSObject>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// WXYZ_DownloadHelperProtocol.h
|
||||
// WXReader
|
||||
//
|
||||
// Created by Andrew on 2020/4/1.
|
||||
// Copyright © 2020 Andrew. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "WXYZ_DownloadManagerEnumProtocol.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol WXYZ_DownloadManagerProtocol <NSObject>
|
||||
|
||||
@optional
|
||||
/*
|
||||
增
|
||||
**/
|
||||
|
||||
// 下载章节
|
||||
- (void)downloadChapterWithProductionModel:(TFProductionModel *)productionModel production_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id;
|
||||
|
||||
// 下载多个章节
|
||||
- (void)downloadChaptersWithProductionModel:(TFProductionModel *)productionModel production_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *>*)chapter_ids;
|
||||
|
||||
/*
|
||||
删
|
||||
**/
|
||||
|
||||
// 删除本地已下载作品
|
||||
- (BOOL)removeDownloadProductionWithProduction_id:(NSInteger)production_id;
|
||||
|
||||
// 删除本地已下载章节
|
||||
- (void)removeDownloadChaptersWithProduction_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *> *)chapter_ids;
|
||||
|
||||
/*
|
||||
查
|
||||
**/
|
||||
|
||||
// 获取下载章节数
|
||||
- (NSInteger)getDownloadChapterCountWithProduction_id:(NSInteger)production_id;
|
||||
|
||||
// 获取全部已下载章节model
|
||||
- (NSArray *__nullable)getDownloadChapterModelArrayWithProduction_id:(NSInteger)production_id;
|
||||
|
||||
// 获取已下载章节model
|
||||
- (id)getDownloadChapterModelWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id;
|
||||
|
||||
// 获取章节下载状态
|
||||
- (WXYZ_ProductionDownloadState)getChapterDownloadStateWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id;
|
||||
|
||||
// 章节是否下载
|
||||
- (BOOL)isChapterDownloadedWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
Reference in New Issue
Block a user