Commit 57857b20dcf0fd071b2b2dc1d04924a599faf825

Authored by yinqiaojuan
1 parent df2d2fde

0.0.1

Showing 42 changed files with 3019 additions and 0 deletions
.gitignore 0 → 100644
  1 +# OS X
  2 +.DS_Store
  3 +
  4 +# Xcode
  5 +build/
  6 +Products/
  7 +*.pbxuser
  8 +!default.pbxuser
  9 +*.mode1v3
  10 +!default.mode1v3
  11 +*.mode2v3
  12 +!default.mode2v3
  13 +*.perspectivev3
  14 +!default.perspectivev3
  15 +xcuserdata/
  16 +*.xccheckout
  17 +profile
  18 +*.moved-aside
  19 +DerivedData
  20 +*.hmap
  21 +*.ipa
  22 +
  23 +# Bundler
  24 +.bundle
  25 +
  26 +# Add this line if you want to avoid checking in source code from Carthage dependencies.
  27 +# Carthage/Checkouts
  28 +
  29 +Carthage/Build
  30 +
  31 +# We recommend against adding the Pods directory to your .gitignore. However
  32 +# you should judge for yourself, the pros and cons are mentioned at:
  33 +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
  34 +#
  35 +# Note: if you ignore the Pods directory, make sure to uncomment
  36 +# `pod install` in .travis.yml
  37 +#
  38 +# Pods/
... ...
.travis.yml 0 → 100644
  1 +# references:
  2 +# * https://www.objc.io/issues/6-build-tools/travis-ci/
  3 +# * https://github.com/supermarin/xcpretty#usage
  4 +
  5 +osx_image: xcode7.3
  6 +language: objective-c
  7 +# cache: cocoapods
  8 +# podfile: Example/Podfile
  9 +# before_install:
  10 +# - gem install cocoapods # Since Travis is not always on latest version
  11 +# - pod install --project-directory=Example
  12 +script:
  13 +- set -o pipefail && xcodebuild test -enableCodeCoverage YES -workspace Example/CNLiveDownloadManager.xcworkspace -scheme CNLiveDownloadManager-Example -sdk iphonesimulator9.3 ONLY_ACTIVE_ARCH=NO | xcpretty
  14 +- pod lib lint
... ...
CNLiveDownloadManager.podspec 0 → 100644
  1 +
  2 +Pod::Spec.new do |s|
  3 + s.name = 'CNLiveDownloadManager'
  4 + s.version = '0.0.1'
  5 + s.summary = '下载管理器'
  6 +
  7 + s.description = <<-DESC
  8 +TODO: Add long description of the pod here.
  9 + DESC
  10 +
  11 + s.homepage = 'http://bj.gitlab.cnlive.com/ios-team/CNLiveDownloadManager'
  12 + # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
  13 + s.license = { :type => 'MIT', :file => 'LICENSE' }
  14 + s.author = { '殷巧娟' => '1427945373@qq.com' }
  15 + s.source = { :git => 'http://bj.gitlab.cnlive.com/ios-team/CNLiveDownloadManager.git', :tag => s.version.to_s }
  16 + # s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'
  17 +
  18 + s.ios.deployment_target = '9.0'
  19 +
  20 + # s.source_files = 'CNLiveDownloadManager/Classes/**/*'
  21 +
  22 + # s.resource_bundles = {
  23 + # 'CNLiveDownloadManager' => ['CNLiveDownloadManager/Assets/*.png']
  24 + # }
  25 +
  26 + # s.public_header_files = 'Pod/Classes/**/*.h'
  27 + s.subspec 'Model' do |model|
  28 + model.dependency 'CNLiveBaseKit'
  29 + model.dependency 'CNLiveTripartiteManagement/FMDB'
  30 + model.source_files = 'CNLiveDownloadManager/Classes/Model/*.{h,m}'
  31 + end
  32 + s.subspec 'ViewModel' do |viewModel|
  33 + viewModel.dependency 'CNLiveTripartiteManagement/FMDB'
  34 + viewModel.source_files = 'CNLiveDownloadManager/Classes/ViewModel/*.{h,m}'
  35 + viewModel.dependency 'CNLiveDownloadManager/Model'
  36 + viewModel.dependency 'CNLiveBaseTools'
  37 + viewModel.dependency 'CNLiveEnvironmentConfiguration'
  38 + viewModel.dependency 'CNLiveBusinessTools'
  39 + viewModel.dependency 'CNLiveBaseKit'
  40 + viewModel.dependency 'CNLiveRequestBastKit'
  41 + viewModel.dependency 'CNLiveTripartiteManagement/QMUIKit'
  42 + end
  43 + s.frameworks = 'UIKit', 'Foundation'
  44 + # s.dependency 'CNLiveTripartiteManagement/FMDB'
  45 + # s.dependency 'CNLiveBaseKit'
  46 + # s.dependency 'CNLiveTripartiteManagement/MJExtension'
  47 +end
... ...
CNLiveDownloadManager/Assets/.gitkeep 0 → 100644
CNLiveDownloadManager/Classes/Model/CNLiveAlbumAudioListModel.h 0 → 100644
  1 +//
  2 +// CNLiveAlbumAudioListModel.h
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/1.
  6 +//
  7 +
  8 +#import <Foundation/Foundation.h>
  9 +#import "CNLiveAlbumMsgModel.h"
  10 +#import <FMDB/FMDB.h>
  11 +NS_ASSUME_NONNULL_BEGIN
  12 +typedef NS_ENUM(NSInteger, CNDownloadState) {
  13 + CNDownloadStateDefault = 0, // 默认
  14 + CNDownloadStateDownloading, // 正在下载
  15 + CNDownloadStateWaiting, // 等待
  16 + CNDownloadStatePaused, // 暂停
  17 + CNDownloadStateFinish, // 完成
  18 + CNDownloadStateError, // 错误
  19 + CNDownloadStatePausedNoNetwork, //无网的时候暂停和退到后台暂停
  20 +};
  21 +@interface CNLiveAlbumAudioListModel : NSObject
  22 +@property (nonatomic, copy) NSString *activityId; //活动ID
  23 +@property (nonatomic, copy) NSString *title; //标题名称
  24 +@property (nonatomic, copy) NSString *albumId; //专辑ID
  25 +@property (nonatomic, copy) NSString *albumName; //专辑名称
  26 +@property (nonatomic, copy) NSString *actor; //作者
  27 +@property (nonatomic, copy) NSString *modelId; //类型ID,5是音频
  28 +@property (nonatomic, copy) NSString *time;
  29 +@property (nonatomic, copy) NSString *img;
  30 +@property (nonatomic, copy) NSString *counts; //后面标题号
  31 +@property (nonatomic, copy) NSString *viewCounts; //人数
  32 +@property (nonatomic, copy) NSString *schedule; //播放长度
  33 +@property (nonatomic, copy) NSString *comments; //评论数
  34 +@property (nonatomic, copy) NSString *contentId;
  35 +@property (nonatomic, copy) NSString *duration; //时长
  36 +@property (nonatomic, copy) NSString *shareUrl;
  37 +@property (nonatomic, copy) NSString * aid; //专辑ID
  38 +@property (nonatomic, copy) NSString * poster; //封面图
  39 +@property (nonatomic, copy) NSString * channelName; //
  40 + // 播放详情接口
  41 +@property (nonatomic, strong) CNLiveAlbumMsgModel * album; //专辑
  42 +@property (nonatomic, copy) NSString * desc; //描述
  43 +@property (nonatomic, copy) NSString * model; //
  44 +@property (nonatomic, copy) NSString * publishTime; //
  45 +@property (nonatomic, copy) NSString * siteId; //
  46 +@property (nonatomic, copy) NSString * subTitle;
  47 +@property (nonatomic, copy) NSString *isSelected; //是否被播放过
  48 + // 历史记录
  49 +@property (nonatomic, copy) NSString *recordId;
  50 +@property (nonatomic, copy) NSString *activeId;
  51 +@property (nonatomic, copy) NSString *recent;
  52 +@property (nonatomic, copy) NSString *sid;
  53 +@property (nonatomic, copy) NSString *albumImg;
  54 +@property (nonatomic, copy) NSString *number; //展示前面的数字,自己加的
  55 +@property (nonatomic, copy) NSString *isCellSelected; //cell是否被选中
  56 + //下载的数据
  57 +@property (nonatomic, copy) NSString *localPath; // 下载完成路径
  58 +@property (nonatomic, copy) NSString *url; // url
  59 +@property (nonatomic, strong) NSData *resumeData; // 下载的数据
  60 +@property (nonatomic, assign) CGFloat progress; // 下载进度
  61 +@property (nonatomic, assign) CNDownloadState state; // 下载状态
  62 +@property (nonatomic, assign) NSUInteger totalFileSize; // 文件总大小
  63 +@property (nonatomic, assign) NSUInteger tmpFileSize; // 下载大小
  64 +@property (nonatomic, assign) NSUInteger speed; // 下载速度
  65 +@property (nonatomic, assign) NSTimeInterval lastSpeedTime; // 上次计算速度时的时间戳
  66 +@property (nonatomic, assign) NSUInteger intervalFileSize; // 计算速度时间内下载文件的大小
  67 +@property (nonatomic, assign) NSUInteger lastStateTime; // 记录任务加入准备下载的时间(点击默认、暂停、失败状态),用于计算开始、停止任务的先后顺序
  68 +@property (nonatomic, copy) NSString *fileSize; //服务器返的文件大小
  69 +
  70 + // 根据数据库查询结果初始化
  71 +- (instancetype)initWithFMResultSet:(FMResultSet *)resultSet;
  72 +@end
  73 +
  74 +NS_ASSUME_NONNULL_END
... ...
CNLiveDownloadManager/Classes/Model/CNLiveAlbumAudioListModel.m 0 → 100644
  1 +//
  2 +// CNLiveAlbumAudioListModel.m
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/1.
  6 +//
  7 +
  8 +#import "CNLiveAlbumAudioListModel.h"
  9 +#import "MJExtension.h"
  10 +@implementation CNLiveAlbumAudioListModel
  11 ++ (NSDictionary *)mj_replacedKeyFromPropertyName
  12 +{
  13 + return @{
  14 + @"recordId":@"id",
  15 + };
  16 +}
  17 +- (NSString *)localPath {
  18 + if (!_localPath) {
  19 + if (_url && ![_url isEqualToString:@"<null>"]) {
  20 + NSString *fileName = [_url substringFromIndex:[_url rangeOfString:@"/" options:NSBackwardsSearch].location + 1];
  21 + NSString *str = [NSString stringWithFormat:@"%@_%@", _activityId, fileName];
  22 + NSString *fileCacheDireCtory = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"albumAudioList_%@",_albumId]];
  23 + _localPath = [fileCacheDireCtory stringByAppendingPathComponent:str];
  24 + }
  25 + }
  26 +
  27 + return _localPath ? _localPath: @"";
  28 +}
  29 +- (instancetype)initWithFMResultSet:(FMResultSet *)resultSet {
  30 + if (!resultSet) return nil;
  31 + _activityId = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"activityId"]];
  32 + _contentId = [NSString stringWithFormat:@"%@", [resultSet objectForColumn:@"contentId"]];
  33 + _title = [NSString stringWithFormat:@"%@", [resultSet objectForColumn:@"title"]];
  34 + _albumName = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"albumName"]];
  35 + _albumId = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"albumId"]];
  36 + _img = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"img"]];
  37 + _shareUrl = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"shareUrl"]];
  38 + _counts = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"counts"]];
  39 + _viewCounts = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"viewCounts"]];
  40 + _actor = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"actor"]];
  41 + _duration = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"duration"]];
  42 + _modelId = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"modelId"]];
  43 + _schedule = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"schedule"]];
  44 + _channelName = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"channelName"]];
  45 + _time = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"time"]];
  46 + _url = [NSString stringWithFormat:@"%@", [resultSet objectForColumn:@"url"]];
  47 + _resumeData = [resultSet dataForColumn:@"resumeData"];
  48 + _totalFileSize = [[resultSet objectForColumn:@"totalFileSize"] integerValue];
  49 + _tmpFileSize = [[resultSet objectForColumn:@"tmpFileSize"] integerValue];
  50 + _state = [[resultSet objectForColumn:@"state"] integerValue];
  51 + _progress = [[resultSet objectForColumn:@"progress"] floatValue];
  52 + _lastSpeedTime = [resultSet doubleForColumn:@"lastSpeedTime"];
  53 + _intervalFileSize = [[resultSet objectForColumn:@"intervalFileSize"] integerValue];
  54 + _lastStateTime = [[resultSet objectForColumn:@"lastStateTime"] integerValue];
  55 + _fileSize = [NSString stringWithFormat:@"%@",[resultSet objectForColumn:@"fileSize"]];
  56 +
  57 + return self;
  58 +}
  59 +
  60 +@end
... ...
CNLiveDownloadManager/Classes/Model/CNLiveAlbumMsgModel.h 0 → 100644
  1 +//
  2 +// CNLiveAlbumMsgModel.h
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/1.
  6 +//
  7 +
  8 +#import <Foundation/Foundation.h>
  9 +@class CNLiveAlbumMsgSpModel;
  10 +NS_ASSUME_NONNULL_BEGIN
  11 +
  12 +@interface CNLiveAlbumMsgModel : NSObject
  13 +@property (nonatomic, copy) NSString *albumId;
  14 +@property (nonatomic, copy) NSString *albumImg; //图片地址
  15 +@property (nonatomic, copy) NSString *albumName; //标题
  16 +@property (nonatomic, copy) NSString *desc; //描述
  17 +@property (nonatomic, copy) NSString *actor;
  18 +@property (nonatomic, copy) NSString *time; //时间戳
  19 +@property (nonatomic, copy) NSString *episodeNow; //总集数
  20 +@property (nonatomic, strong) CNLiveAlbumMsgSpModel *sp; //下面简介
  21 +@property (nonatomic, copy) NSString *subscriptions;
  22 +@property (nonatomic, copy) NSString *subscribe;
  23 +@property (nonatomic, copy) NSString *episodeLast; //最后一次播放的章节数
  24 +@property (nonatomic, copy) NSString *contentIdLast;
  25 +- (CGFloat)setRowHeight;
  26 +@end
  27 +@interface CNLiveAlbumMsgSpModel : NSObject
  28 +@property (nonatomic, copy) NSString *spName; //
  29 +@property (nonatomic, copy) NSString *spId; //
  30 +@property (nonatomic, copy) NSString *spIcon; //
  31 +@property (nonatomic, copy) NSString *desc; //
  32 +@property (nonatomic, copy) NSString *subscriptions; //
  33 +@property (nonatomic, copy) NSString *subscribe; //
  34 +@end
  35 +
  36 +NS_ASSUME_NONNULL_END
... ...
CNLiveDownloadManager/Classes/Model/CNLiveAlbumMsgModel.m 0 → 100644
  1 +//
  2 +// CNLiveAlbumMsgModel.m
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/1.
  6 +//
  7 +
  8 +#import "CNLiveAlbumMsgModel.h"
  9 +#import <CNLiveBaseKit/CNLiveDefinesHeader.h>
  10 +@implementation CNLiveAlbumMsgModel
  11 ++ (NSDictionary *)mj_objectClassInArray{
  12 + return @{
  13 + @"sp" : @"CNLiveAlbumMsgSpModel"
  14 + };
  15 +}
  16 +- (CGFloat)setRowHeight {
  17 + NSDictionary *descAttr = @{NSFontAttributeName:UIFontCNMake(16)};
  18 + CGFloat descHeight = [self.desc boundingRectWithSize:CGSizeMake(KScreenWidth - 20, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:descAttr context:nil].size.height;
  19 + return descHeight;
  20 +}
  21 +@end
  22 +@implementation CNLiveAlbumMsgSpModel
  23 +
  24 +@end
  25 +
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveDataBaseManager.h 0 → 100644
  1 +//
  2 +// CNLiveDataBaseManager.h
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/1.
  6 +//
  7 +
  8 +#import <Foundation/Foundation.h>
  9 +@class CNLiveAlbumAudioListModel;
  10 +NS_ASSUME_NONNULL_BEGIN
  11 +typedef NS_OPTIONS(NSUInteger, CNDBUpdateOption) {
  12 + CNDBUpdateOptionState = 1 << 0, // 更新状态
  13 + CNDBUpdateOptionLastStateTime = 1 << 1, // 更新状态最后改变的时间
  14 + CNDBUpdateOptionResumeData = 1 << 2, // 更新下载的数据
  15 + CNDBUpdateOptionProgressData = 1 << 3, // 更新进度数据(包含tmpFileSize、totalFileSize、progress、intervalFileSize、lastSpeedTime)
  16 + CNDBUpdateOptionAllParam = 1 << 4 // 更新全部数据
  17 +};
  18 +@interface CNLiveDataBaseManager : NSObject
  19 + // 获取单例
  20 ++ (instancetype)shareManager;
  21 + // 插入数据
  22 +- (void)insertModel:(CNLiveAlbumAudioListModel *)model;
  23 +
  24 + // 获取数据
  25 +- (CNLiveAlbumAudioListModel *)getModelWithUrl:(NSString *)url; // 根据url获取数据
  26 +- (CNLiveAlbumAudioListModel *)getWaitingModel; // 获取第一条等待的数据
  27 +- (CNLiveAlbumAudioListModel *)getLastDownloadingModel; // 获取最后一条正在下载的数据
  28 +- (NSArray<CNLiveAlbumAudioListModel *> *)getAllCacheData; // 获取所有数据
  29 +- (NSArray<CNLiveAlbumAudioListModel *> *)getAllDownloadingData; // 根据lastStateTime倒叙获取所有正在下载的数据
  30 +- (NSArray<CNLiveAlbumAudioListModel *> *)getAllDownloadedData; // 获取所有下载完成的数据
  31 +- (NSArray<CNLiveAlbumAudioListModel *> *)getAllUnDownloadedData; // 获取所有未下载完成的数据(包含正在下载、等待、暂停、错误)
  32 +- (NSArray<CNLiveAlbumAudioListModel *> *)getAllWaitingData; // 获取所有等待下载的数据
  33 +- (CNLiveAlbumAudioListModel *)getModelwithActivityId:(NSString *)activityId; //根据ativityId获取数据
  34 + // 更新数据
  35 +- (void)updateWithModel:(CNLiveAlbumAudioListModel *)model option:(CNDBUpdateOption)option;
  36 +
  37 + // 删除数据
  38 +- (void)deleteModelWithUrl:(NSString *)activityId;
  39 +@end
  40 +
  41 +NS_ASSUME_NONNULL_END
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveDataBaseManager.m 0 → 100644
  1 +//
  2 +// CNLiveDataBaseManager.m
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/1.
  6 +//
  7 +
  8 +#import "CNLiveDataBaseManager.h"
  9 +#import "CNLiveTimeTools.h"
  10 +#import "CNLiveDownloadManager.h"
  11 +#import "CNLiveAlbumAudioListModel.h"
  12 +#import "CNLiveTimeTools.h"
  13 +#import "CNLiveDownload.h"
  14 +typedef NS_ENUM(NSInteger, CNDBGetDateOption) {
  15 + CNDBGetDateOptionAllCacheData = 0, // 所有缓存数据
  16 + CNDBGetDateOptionAllDownloadingData, // 所有正在下载的数据
  17 + CNDBGetDateOptionAllDownloadedData, // 所有下载完成的数据
  18 + CNDBGetDateOptionAllUnDownloadedData, // 所有未下载完成的数据
  19 + CNDBGetDateOptionAllWaitingData, // 所有等待下载的数据
  20 + CNDBGetDateOptionModelWithUrl, // 通过url获取单条数据
  21 + CNDBGetDateOptionWaitingModel, // 第一条等待的数据
  22 + CNDBGetDateOptionLastDownloadingModel, // 最后一条正在下载的数据
  23 + CNDBGetDateOptionModelWithActivityId, //通过activityId获取model
  24 +};
  25 +@interface CNLiveDataBaseManager ()
  26 +@property (nonatomic, strong) FMDatabaseQueue *dbQueue;
  27 +@end
  28 +@implementation CNLiveDataBaseManager
  29 ++ (instancetype)shareManager
  30 +{
  31 + static CNLiveDataBaseManager *manager = nil;
  32 +
  33 + static dispatch_once_t onceToken;
  34 + dispatch_once(&onceToken, ^{
  35 + manager = [[self alloc] init];
  36 + });
  37 +
  38 + return manager;
  39 +}
  40 +
  41 +- (instancetype)init
  42 +{
  43 + if (self = [super init]) {
  44 + [self creatVideoCachesTable];
  45 + }
  46 +
  47 + return self;
  48 +}
  49 +#pragma mark - 创建一个数据库
  50 +- (void)creatVideoCachesTable
  51 +{
  52 + // 数据库文件路径
  53 + NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"CNDownloadVideoCaches.sqlite"];
  54 + // 创建队列对象,内部会自动创建一个数据库, 并且自动打开
  55 + _dbQueue = [FMDatabaseQueue databaseQueueWithPath:path];
  56 +
  57 + [_dbQueue inDatabase:^(FMDatabase *db) {
  58 + // 创表
  59 + BOOL result = [db executeUpdate:@"CREATE TABLE IF NOT EXISTS t_videoCaches (id integer PRIMARY KEY AUTOINCREMENT, activityId text, contentId text,title text,albumName text,albumId text,img text,shareUrl text,counts text,viewCounts text,actor text,duration text,modelId text,schedule text,channelName text,time text,url text, resumeData blob, totalFileSize integer, tmpFileSize integer, state integer, progress float, lastSpeedTime double, intervalFileSize integer, lastStateTime integer, fileSize text)"];
  60 + if (![db columnExists:@"channelName" inTableWithName:@"t_videoCaches"] ) { //新添字段,先判断数据里有没有,没有,添加
  61 + NSString *channelName = [NSString stringWithFormat:@"ALTER TABLE %@ ADD %@ INTEGER",@"t_videoCaches",@"channelName"];
  62 + BOOL isSuccess = [db executeUpdate:channelName];
  63 + if (isSuccess) {
  64 + NSLog(@"插入成功");
  65 + }else {
  66 + NSLog(@"插入失败");
  67 + }
  68 + }
  69 + if (result) {
  70 + NSLog(@"音频缓存数据表创建成功");
  71 + }else {
  72 + NSLog(@"音频缓存数据表创建失败");
  73 + }
  74 + }];
  75 +}
  76 +
  77 +#pragma mark - 插入一条数据
  78 +- (void)insertModel:(CNLiveAlbumAudioListModel *)model
  79 +{
  80 + [_dbQueue inDatabase:^(FMDatabase *db) {
  81 + BOOL result = [db executeUpdate:@"INSERT INTO t_videoCaches (activityId,contentId,title,albumName,albumId,img,shareUrl,counts,viewCounts,actor,duration,modelId,schedule,channelName,time,url, resumeData, totalFileSize, tmpFileSize, state, progress, lastSpeedTime, intervalFileSize, lastStateTime, fileSize) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)", model.activityId?model.activityId :[NSNull null],model.contentId?model.contentId:[NSNull null], model.title?model.title:[NSNull null],model.albumName ? model.albumName:[NSNull null],model.albumId?model.albumId:[NSNull null],model.img?model.img:[NSNull null],model.shareUrl?model.shareUrl:[NSNull null],model.counts?model.counts:[NSNull null],model.viewCounts?model.viewCounts:[NSNull null],model.actor ? model.actor:[NSNull null],model.duration ? model.duration:[NSNull null],model.modelId ?model.modelId :[NSNull null],model.schedule ?model.schedule:[NSNull null],model.channelName ? model.channelName:[NSNull null],model.time ? model.time:[NSNull null],model.url, model.resumeData, [NSNumber numberWithInteger:model.totalFileSize], [NSNumber numberWithInteger:model.tmpFileSize], [NSNumber numberWithInteger:model.state], [NSNumber numberWithFloat:model.progress], [NSNumber numberWithDouble:0], [NSNumber numberWithInteger:0], [NSNumber numberWithInteger:0],model.fileSize];
  82 + if (result) {
  83 + NSLog(@"插入成功:%@", model.title);
  84 + }else {
  85 + NSLog(@"插入失败:%@", model.title);
  86 + }
  87 + }];
  88 +}
  89 +#pragma mark - 根据url获取单条数据
  90 +- (CNLiveAlbumAudioListModel *)getModelWithUrl:(NSString *)url
  91 + {
  92 + return [self getModelWithOption:CNDBGetDateOptionModelWithUrl url:url activityId:nil];
  93 + }
  94 +#pragma mark - 根据activityId获取Model
  95 +- (CNLiveAlbumAudioListModel *)getModelwithActivityId:(NSString *)activityId {
  96 + return [self getModelWithOption:CNDBGetDateOptionModelWithActivityId url:nil activityId:activityId];
  97 +}
  98 +#pragma mark - 获取第一条等待的数据
  99 +- (CNLiveAlbumAudioListModel *)getWaitingModel
  100 + {
  101 + return [self getModelWithOption:CNDBGetDateOptionWaitingModel url:nil activityId:nil];
  102 + }
  103 +#pragma mark - 获取正在下载的数据
  104 +- (CNLiveAlbumAudioListModel *)getLastDownloadingModel
  105 + {
  106 + return [self getModelWithOption:CNDBGetDateOptionLastDownloadingModel url:nil activityId:nil];
  107 + }
  108 +
  109 +#pragma mark - 获取所有数据
  110 +- (NSArray<CNLiveAlbumAudioListModel *> *)getAllCacheData
  111 + {
  112 + return [self getDateWithOption:CNDBGetDateOptionAllCacheData];
  113 + }
  114 +#pragma mark - 根据lastStateTime倒叙获取所有正在下载的数据
  115 +- (NSArray<CNLiveAlbumAudioListModel *> *)getAllDownloadingData
  116 + {
  117 + return [self getDateWithOption:CNDBGetDateOptionAllDownloadingData];
  118 + }
  119 +#pragma mark - 获取所有下载完成的数据
  120 +- (NSArray<CNLiveAlbumAudioListModel *> *)getAllDownloadedData
  121 + {
  122 + return [self getDateWithOption:CNDBGetDateOptionAllDownloadedData];
  123 + }
  124 +#pragma mark - 获取所有未下载完成的数据
  125 +- (NSArray<CNLiveAlbumAudioListModel *> *)getAllUnDownloadedData
  126 + {
  127 + return [self getDateWithOption:CNDBGetDateOptionAllUnDownloadedData];
  128 + }
  129 +#pragma mark - 获取所有等待下载的数据
  130 +- (NSArray<CNLiveAlbumAudioListModel *> *)getAllWaitingData
  131 + {
  132 + return [self getDateWithOption:CNDBGetDateOptionAllWaitingData];
  133 + }
  134 +#pragma mark - 获取单条数据
  135 +- (CNLiveAlbumAudioListModel *)getModelWithOption:(CNDBGetDateOption)option url:(NSString *)url activityId:(NSString *)activityId
  136 + {
  137 + __block CNLiveAlbumAudioListModel *model = nil;
  138 +
  139 + [_dbQueue inDatabase:^(FMDatabase *db) {
  140 + FMResultSet *resultSet;
  141 + switch (option) {
  142 + case CNDBGetDateOptionModelWithUrl:
  143 + resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE url = ?", url];
  144 + break;
  145 +
  146 + case CNDBGetDateOptionWaitingModel:
  147 + resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ? order by lastStateTime asc limit 0,1", [NSNumber numberWithInteger:CNDownloadStateWaiting]];
  148 + break;
  149 +
  150 + case CNDBGetDateOptionLastDownloadingModel:
  151 + resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ? order by lastStateTime desc limit 0,1", [NSNumber numberWithInteger:CNDownloadStateDownloading]];
  152 + break;
  153 + case CNDBGetDateOptionModelWithActivityId:
  154 + resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE activityId = ?", activityId];
  155 + break;
  156 + default:
  157 + break;
  158 + }
  159 +
  160 + while ([resultSet next]) {
  161 + model = [[CNLiveAlbumAudioListModel alloc] initWithFMResultSet:resultSet];
  162 + }
  163 + }];
  164 +
  165 + return model;
  166 + }
  167 +#pragma mark - 获取数据集合
  168 +- (NSArray<CNLiveAlbumAudioListModel *> *)getDateWithOption:(CNDBGetDateOption)option
  169 + {
  170 + __block NSArray<CNLiveAlbumAudioListModel *> *array = nil;
  171 +
  172 + [_dbQueue inDatabase:^(FMDatabase *db) {
  173 + FMResultSet *resultSet;
  174 + switch (option) {
  175 +
  176 + case CNDBGetDateOptionAllCacheData:
  177 + resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches"];
  178 + break;
  179 +
  180 + case CNDBGetDateOptionAllDownloadingData:
  181 + resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ? order by lastStateTime desc", [NSNumber numberWithInteger:CNDownloadStateDownloading]];
  182 + break;
  183 +
  184 + case CNDBGetDateOptionAllDownloadedData:
  185 + resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ?", [NSNumber numberWithInteger:CNDownloadStateFinish]];
  186 + break;
  187 +
  188 + case CNDBGetDateOptionAllUnDownloadedData:
  189 + resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state != ?", [NSNumber numberWithInteger:CNDownloadStateFinish]];
  190 + break;
  191 +
  192 + case CNDBGetDateOptionAllWaitingData:
  193 + resultSet = [db executeQuery:@"SELECT * FROM t_videoCaches WHERE state = ?", [NSNumber numberWithInteger:CNDownloadStateWaiting]];
  194 + break;
  195 +
  196 + default:
  197 + break;
  198 + }
  199 +
  200 + NSMutableArray *tmpArr = [NSMutableArray array];
  201 + while ([resultSet next]) {
  202 + [tmpArr addObject:[[CNLiveAlbumAudioListModel alloc] initWithFMResultSet:resultSet]];
  203 + }
  204 + array = tmpArr;
  205 + }];
  206 +
  207 + return array;
  208 + }
  209 +#pragma mark - 更新数据
  210 +- (void)updateWithModel:(CNLiveAlbumAudioListModel *)model option:(CNDBUpdateOption)option
  211 + {
  212 + [_dbQueue inDatabase:^(FMDatabase *db) {
  213 + if (option & CNDBUpdateOptionState) {
  214 + //根据url 更新state数据
  215 + [self postStateChangeNotificationWithFMDatabase:db model:model];
  216 + [db executeUpdate:@"UPDATE t_videoCaches SET state = ?,url = ? WHERE activityId = ?", [NSNumber numberWithInteger:model.state], model.url,model.activityId];
  217 + }
  218 + if (option & CNDBUpdateOptionLastStateTime) {
  219 + [db executeUpdate:@"UPDATE t_videoCaches SET lastStateTime = ?,url = ? WHERE activityId = ?", [NSNumber numberWithInteger:[CNLiveTimeTools getTimeStampWithDate:[NSDate date]]], model.url,model.activityId];
  220 + }
  221 + if (option & CNDBUpdateOptionResumeData) {
  222 + [db executeUpdate:@"UPDATE t_videoCaches SET resumeData = ?,url = ? WHERE activityId = ?", model.resumeData, model.url,model.activityId];
  223 + }
  224 + if (option & CNDBUpdateOptionProgressData) {
  225 + [db executeUpdate:@"UPDATE t_videoCaches SET tmpFileSize = ?, totalFileSize = ?, progress = ?, lastSpeedTime = ?, intervalFileSize = ?,url = ? WHERE activityId = ?", [NSNumber numberWithInteger:model.tmpFileSize], [NSNumber numberWithFloat:model.totalFileSize], [NSNumber numberWithFloat:model.progress], [NSNumber numberWithDouble:model.lastSpeedTime], [NSNumber numberWithInteger:model.intervalFileSize], model.url,model.activityId];
  226 + }
  227 + if (option & CNDBUpdateOptionAllParam) {
  228 + [self postStateChangeNotificationWithFMDatabase:db model:model];
  229 + [db executeUpdate:@"UPDATE t_videoCaches SET resumeData = ?, totalFileSize = ?, tmpFileSize = ?, progress = ?, state = ?, lastSpeedTime = ?, intervalFileSize = ?, lastStateTime = ? ,url = ? WHERE activityId = ?", model.resumeData, [NSNumber numberWithInteger:model.totalFileSize], [NSNumber numberWithInteger:model.tmpFileSize], [NSNumber numberWithFloat:model.progress], [NSNumber numberWithInteger:model.state], [NSNumber numberWithDouble:model.lastSpeedTime], [NSNumber numberWithInteger:model.intervalFileSize], [NSNumber numberWithInteger:[CNLiveTimeTools getTimeStampWithDate:[NSDate date]]], model.url,model.activityId];
  230 + }
  231 + }];
  232 + }
  233 +
  234 +
  235 +#pragma mark - 状态改变通知
  236 +- (void)postStateChangeNotificationWithFMDatabase:(FMDatabase *)db model:(CNLiveAlbumAudioListModel *)model
  237 + {
  238 + // 原状态
  239 + //t_videoCaches创建的表名 where通过什么查询 通过url查询state
  240 + NSInteger oldState = [db intForQuery:@"SELECT state FROM t_videoCaches WHERE activityId = ?", model.activityId];
  241 +
  242 + if (oldState != model.state && oldState != CNDownloadStateFinish) {
  243 + // 状态变更通知
  244 + [[NSNotificationCenter defaultCenter] postNotificationName:WjjAudioDownloadStateChangeNotification object:model];
  245 + }
  246 + }
  247 +#pragma mark - 删除数据库数据
  248 +- (void)deleteModelWithUrl:(NSString *)activityId
  249 + {
  250 + [_dbQueue inDatabase:^(FMDatabase *db) { // where 后面跟的是条件
  251 + BOOL result = [db executeUpdate:@"DELETE FROM t_videoCaches WHERE activityId = ?", activityId];
  252 + if (result) {
  253 + // HWLog(@"删除成功:%@", url);
  254 + }else {
  255 + NSLog(@"删除失败:%@", activityId);
  256 + }
  257 + }];
  258 + }
  259 +
  260 +
  261 +@end
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveDownload.h 0 → 100644
  1 +//
  2 +// CNLiveDownload.h
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/1.
  6 +//
  7 +
  8 +#ifndef CNLiveDownload_h
  9 +#define CNLiveDownload_h
  10 +
  11 +//分类-听见中国 -下载状态通知
  12 +#ifndef WjjAudioDownloadStateChangeNotification
  13 +#define WjjAudioDownloadStateChangeNotification @"CNDownloadStateChangeNotification"
  14 +#endif
  15 +//分类-听见中国 -下载进度通知
  16 +#ifndef WjjAudioDownloadProgressNotification
  17 +#define WjjAudioDownloadProgressNotification @"CNDownloadProgressNotification"
  18 +#endif
  19 +#endif /* CNLiveDownload_h */
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveDownloadManager.h 0 → 100644
  1 +//
  2 +// CNLiveDownloadManager.h
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/1.
  6 +//
  7 +
  8 +#import <Foundation/Foundation.h>
  9 +@class CNLiveAlbumAudioListModel;
  10 +NS_ASSUME_NONNULL_BEGIN
  11 +@interface CNLiveDownloadManager : NSObject
  12 + // 开始下载
  13 +- (void)startDownloadTask:(CNLiveAlbumAudioListModel *)model;
  14 +
  15 + // 暂停下载
  16 +- (void)pauseDownloadTask:(CNLiveAlbumAudioListModel *)model;
  17 +
  18 + // 删除下载任务及本地缓存
  19 +- (void)deleteTaskAndCache:(CNLiveAlbumAudioListModel *)model;
  20 + //全部暂停
  21 +- (void)pauseAllDownloadTask:(BOOL)isNoHaveNet;
  22 + //全部开始
  23 +- (void)startAllDownloadTask:(BOOL)isHaveNoNet;
  24 + @property (nonatomic, assign) BOOL allowsCellularAccess; // 是否允许蜂窝网络下载
  25 + @property (nonatomic, assign) BOOL isloading; //yes表示有请求download的url在进行
  26 +- (void)getDownloadUrl:(CNLiveAlbumAudioListModel *)model;
  27 +@end
  28 +
  29 +NS_ASSUME_NONNULL_END
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveDownloadManager.m 0 → 100644
  1 +//
  2 +// CNLiveDownloadManager.m
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/1.
  6 +//
  7 +
  8 +#import "CNLiveDownloadManager.h"
  9 +#import "NSString+CNLiveExtension.h"
  10 +#import "CNLiveAlbumAudioListModel.h"
  11 +#import "NSURLSession+CNLiveCorrectedResumeData.h"
  12 +#import "CNLiveVodUrlUtil.h"
  13 +#import "NSString+CNLiveExtension.h"
  14 +#import "CNLiveNetworking.h"
  15 +#import "CNUserInfoManager.h"
  16 +#import "CNLiveDataBaseManager.h"
  17 +#import "CNLiveDefinesHeader.h"
  18 +#import "QMUIKit.h"
  19 +#import "CNLiveTimeTools.h"
  20 +#import "CNLiveDownload.h"
  21 +#define CNLiveAppKeyWindow [UIApplication sharedApplication].delegate.window
  22 +;@interface CNLiveDownloadManager ()<NSURLSessionDelegate,NSURLSessionDownloadDelegate,UIAlertViewDelegate>
  23 +@property (nonatomic, strong) NSURLSession *session; // NSURLSession
  24 +@property (nonatomic, strong) NSMutableDictionary *dataTaskDic; // 同时下载多个文件,需要创建多个NSURLSessionDownloadTask,用该字典来存储
  25 +@property (nonatomic, strong) NSMutableDictionary *downloadTaskDic; // 记录任务调用startDownloadTask:方法时间,禁止同一任务极短时间重复调用,防止状态显示错误
  26 +@property (nonatomic, assign) NSInteger currentCount; // 当前正在下载的个数
  27 +@property (nonatomic, assign) NSInteger maxConcurrentCount; // 最大同时下载数量
  28 +@property (nonatomic, assign) BOOL isNohaveNet; //没网
  29 +@end
  30 +
  31 +@implementation CNLiveDownloadManager
  32 ++ (instancetype)shareManager {
  33 + static CNLiveDownloadManager *manager = nil;
  34 + static dispatch_once_t onceToken;
  35 + dispatch_once(&onceToken, ^{
  36 + manager = [[self alloc] init];
  37 + });
  38 +
  39 + return manager;
  40 +}
  41 +- (instancetype)init
  42 +{
  43 + if (self = [super init]) {
  44 + // 初始化
  45 + _currentCount = 0;
  46 + _maxConcurrentCount = 1;
  47 + _allowsCellularAccess = NO;
  48 + _dataTaskDic = [NSMutableDictionary dictionary];
  49 + _downloadTaskDic = [NSMutableDictionary dictionary];
  50 + // 单线程代理队列
  51 + NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  52 + queue.maxConcurrentOperationCount = 1;
  53 + // 后台下载标识
  54 + NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"CNDownloadBackgroundSessionIdentifier"];
  55 + // 允许蜂窝网络下载,默认为YES,这里开启,我们添加了一个变量去控制用户切换选择
  56 + configuration.allowsCellularAccess = YES;
  57 + // 创建NSURLSession,配置信息、代理、代理线程
  58 + _session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:queue];
  59 + [self monitorTheNetwork];
  60 + [self startDownloadWaitingTask];
  61 + }
  62 +
  63 + return self;
  64 +}
  65 +#pragma mark -请求下载Url
  66 +- (void)getDownloadUrl:(CNLiveAlbumAudioListModel *)model {
  67 + self.isloading = YES;
  68 + [[CNLiveVodUrlUtil manager] getVodUrlWithVid:model.activityId channelName:model.channelName sid:CNUserShareModelUid playType:@"a" tag:@"" completeBlock:^(NSString * _Nonnull vodUrl) {
  69 + if (vodUrl) {
  70 + model.url = vodUrl;
  71 + self.isloading = NO;
  72 + [self startDownloadTask:model];
  73 + }else {
  74 + CNLiveAlbumAudioListModel *downloadModel = [[CNLiveDataBaseManager shareManager] getModelwithActivityId:model.activityId];
  75 + if (!downloadModel) {
  76 + [QMUITips showWithText:@"添加下载失败" inView:CNLiveAppKeyWindow hideAfterDelay:1.5f];
  77 + }else {
  78 + downloadModel.state = CNDownloadStateError;
  79 + [[CNLiveDataBaseManager shareManager] updateWithModel:downloadModel option:CNDBUpdateOptionState | CNDBUpdateOptionLastStateTime];
  80 + }
  81 + //请求失败,继续下载下一个等待的数据
  82 + self.isloading = NO;
  83 + [self startDownloadWaitingTask];
  84 + }
  85 + }];
  86 +}
  87 +#pragma mark -加入准备下载任务
  88 +- (void)startDownloadTask:(CNLiveAlbumAudioListModel *)model
  89 +{
  90 + __weak typeof(self) weakSelf = self;
  91 + // 同一任务,1.0s内禁止重复调用
  92 + if ([[NSDate date] timeIntervalSinceDate:[weakSelf.downloadTaskDic valueForKey:model.activityId]] < 1.0f) return;
  93 + if (!CNLiveStringIsEmpty(model.activityId)) {
  94 + [weakSelf.downloadTaskDic setValue:[NSDate date] forKey:model.activityId];
  95 + }
  96 + // 取出数据库中模型数据,如果不存在,添加到数据库中(注意:需要保证url唯一,若多条目同一url,则要另做处理)
  97 + CNLiveAlbumAudioListModel *downloadModel = [[CNLiveDataBaseManager shareManager] getModelwithActivityId:model.activityId];
  98 + if (!downloadModel) {
  99 + downloadModel = model;
  100 + [[CNLiveDataBaseManager shareManager] insertModel:downloadModel];
  101 + }
  102 + // 更新状态为等待下载
  103 + downloadModel.url = model.url;
  104 + downloadModel.state = CNDownloadStateWaiting;
  105 + [[CNLiveDataBaseManager shareManager] updateWithModel:downloadModel option:CNDBUpdateOptionState | CNDBUpdateOptionLastStateTime];
  106 +
  107 + // 下载(给定一个等待时间,保证currentCount更新)
  108 + [NSThread sleepForTimeInterval:0.1f];
  109 + if ((weakSelf.currentCount < weakSelf.maxConcurrentCount) && [weakSelf networkingAllowsDownloadTask])
  110 + {
  111 + [weakSelf downloadwithModel:downloadModel];
  112 + }
  113 +}
  114 +#pragma mark -开始真正下载
  115 +- (void)downloadwithModel:(CNLiveAlbumAudioListModel *)model
  116 +{
  117 + _currentCount++;
  118 + // cancelByProducingResumeData:回调有延时,给定一个等待时间,重新获取模型,保证获取到resumeData
  119 + [NSThread sleepForTimeInterval:0.3f];
  120 + CNLiveAlbumAudioListModel *downloadModel = [[CNLiveDataBaseManager shareManager] getModelwithActivityId:model.activityId];
  121 +
  122 + // 更新状态为开始
  123 + downloadModel.state = CNDownloadStateDownloading;
  124 + [[CNLiveDataBaseManager shareManager] updateWithModel:downloadModel option:CNDBUpdateOptionState];
  125 +
  126 + // 创建NSURLSessionDownloadTask
  127 + NSURLSessionDownloadTask *downloadTask;
  128 +
  129 + if (downloadModel.resumeData) {
  130 + CGFloat version = [[[UIDevice currentDevice] systemVersion] floatValue];
  131 + if (version >= 10.0 && version < 10.2) {
  132 + downloadTask = [_session downloadTaskWithCorrectResumeData:downloadModel.resumeData];
  133 + }else {
  134 + downloadTask = [_session downloadTaskWithResumeData:downloadModel.resumeData];
  135 + }
  136 +
  137 + }else {
  138 + downloadTask = [_session downloadTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:downloadModel.url]]];
  139 + }
  140 + // 添加描述标签
  141 + downloadTask.taskDescription = downloadModel.url;
  142 +
  143 + // 更新存储的NSURLSessionDownloadTask对象
  144 + if (!CNLiveStringIsEmpty(downloadModel.activityId)) {
  145 + [_dataTaskDic setValue:downloadTask forKey:downloadModel.activityId];
  146 + }
  147 + // 启动(继续下载)
  148 + [downloadTask resume];
  149 +}
  150 +#pragma mark -全部暂停和没网的时候暂停下载中和等待的数据
  151 +- (void)pauseAllDownloadTask:(BOOL)isNoHaveNet{
  152 + __weak typeof(self) weakSelf = self;
  153 + NSArray<CNLiveAlbumAudioListModel*> *downloadTasks = [[CNLiveDataBaseManager shareManager] getAllUnDownloadedData];
  154 + NSInteger count = downloadTasks.count;
  155 + for(NSInteger i=0; i<count; i++){
  156 + CNLiveAlbumAudioListModel *model = downloadTasks[i];
  157 + // 取最新数据
  158 + CNLiveAlbumAudioListModel*downloadModel = [[CNLiveDataBaseManager shareManager] getModelwithActivityId:model.activityId];
  159 + if(downloadModel.state == CNDownloadStateDownloading){
  160 + // 获取NSURLSessionDownloadTask
  161 + NSURLSessionDownloadTask *downloadTask = [_dataTaskDic valueForKey:model.activityId];
  162 + [downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
  163 + // 更新下载数据
  164 + model.resumeData = resumeData;
  165 + [[CNLiveDataBaseManager shareManager] updateWithModel:model option:CNDBUpdateOptionResumeData];
  166 + // 更新当前正在下载的个数
  167 + self.isloading = NO;
  168 + if (weakSelf.currentCount > 0) weakSelf.currentCount--;
  169 + }];
  170 + if (!isNoHaveNet) {
  171 + downloadModel.state = CNDownloadStatePaused;
  172 + }else {
  173 + downloadModel.state = CNDownloadStatePausedNoNetwork;
  174 + }
  175 + }else if (downloadModel.state == CNDownloadStateWaiting){
  176 + if (!isNoHaveNet) {
  177 + downloadModel.state = CNDownloadStatePaused;
  178 + }else{
  179 + downloadModel.state = CNDownloadStatePausedNoNetwork;
  180 + }
  181 + }
  182 + // 更新数据库状态为暂停
  183 + [[CNLiveDataBaseManager shareManager] updateWithModel:downloadModel option:CNDBUpdateOptionState];
  184 + }
  185 +}
  186 +
  187 +#pragma mark -全部开始和无网的开始因无网暂停的下载
  188 +- (void)startAllDownloadTask:(BOOL)isHaveNoNet{
  189 + NSArray<CNLiveAlbumAudioListModel *> *downloadTasks = [[CNLiveDataBaseManager shareManager] getAllUnDownloadedData];
  190 + NSInteger count = downloadTasks.count;
  191 + for(NSInteger i=0; i<count; i++){
  192 + CNLiveAlbumAudioListModel *model = downloadTasks[i];
  193 + // 取最新数据
  194 + CNLiveAlbumAudioListModel *downloadModel = [[CNLiveDataBaseManager shareManager] getModelwithActivityId:model.activityId];
  195 + //暂停,默认,错误
  196 + if (!isHaveNoNet) {
  197 + if(downloadModel.state == CNDownloadStatePaused || downloadModel.state == CNDownloadStatePausedNoNetwork ||downloadModel.state == CNDownloadStateDefault || downloadModel.state == CNDownloadStateError){
  198 + downloadModel.state = CNDownloadStateWaiting;
  199 + [[CNLiveDataBaseManager shareManager] updateWithModel:downloadModel option:CNDBUpdateOptionState | CNDBUpdateOptionLastStateTime];
  200 + }
  201 + }else {
  202 + if(downloadModel.state == CNDownloadStatePausedNoNetwork || downloadModel.state == CNDownloadStateDefault || downloadModel.state == CNDownloadStateError ){
  203 + downloadModel.state = CNDownloadStateWaiting;
  204 + [[CNLiveDataBaseManager shareManager] updateWithModel:downloadModel option:CNDBUpdateOptionState | CNDBUpdateOptionLastStateTime];
  205 + }
  206 + }
  207 + }
  208 + [self startDownloadWaitingTask];
  209 + //获取等待下载的数据,开始下载
  210 +}
  211 +#pragma mark -单条暂停
  212 +- (void)pauseDownloadTask:(CNLiveAlbumAudioListModel *)model
  213 +{
  214 + // 取最新数据
  215 + CNLiveAlbumAudioListModel *downloadModel = [[CNLiveDataBaseManager shareManager] getModelwithActivityId:model.activityId];
  216 +
  217 + // 取消任务
  218 + [self cancelTaskWithModel:downloadModel delete:NO];
  219 +
  220 + // 更新数据库状态为暂停
  221 + downloadModel.state = CNDownloadStatePaused;
  222 + [[CNLiveDataBaseManager shareManager] updateWithModel:downloadModel option:CNDBUpdateOptionState];
  223 +}
  224 +#pragma mark 删除下载任务及本地缓存
  225 +- (void)deleteTaskAndCache:(CNLiveAlbumAudioListModel *)model
  226 +{
  227 + // 如果正在下载,取消任务
  228 + [self cancelTaskWithModel:model delete:YES];
  229 +
  230 + // 删除本地缓存、数据库数据
  231 + dispatch_async(dispatch_get_global_queue(0, 0), ^{
  232 + if (!CNLiveStringIsEmpty(model.localPath)) {
  233 + [[NSFileManager defaultManager] removeItemAtPath:model.localPath error:nil];
  234 + [[CNLiveDataBaseManager shareManager] deleteModelWithUrl:model.activityId];
  235 + }else {
  236 + [[CNLiveDataBaseManager shareManager] deleteModelWithUrl:model.activityId];
  237 + }
  238 + });
  239 +}
  240 +
  241 +#pragma mark -取消任务
  242 +- (void)cancelTaskWithModel:(CNLiveAlbumAudioListModel *)model delete:(BOOL)delete
  243 +{
  244 + __weak typeof(self) weakSelf = self;
  245 + if (model.state == CNDownloadStateDownloading) {
  246 + // 获取NSURLSessionDownloadTask
  247 + NSURLSessionDownloadTask *downloadTask = [_dataTaskDic valueForKey:model.activityId];
  248 +
  249 + // 取消任务
  250 + [downloadTask cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
  251 + // 更新下载数据
  252 + model.resumeData = resumeData;
  253 + [[CNLiveDataBaseManager shareManager] updateWithModel:model option:CNDBUpdateOptionResumeData];
  254 + // 更新当前正在下载的个数
  255 + if (weakSelf.currentCount > 0) weakSelf.currentCount--;
  256 +
  257 + // 开启等待下载任务
  258 + [weakSelf startDownloadWaitingTask];
  259 + }];
  260 +
  261 + // 移除字典存储的对象
  262 + if (delete) {
  263 + if (!CNLiveStringIsEmpty(model.activityId)) {
  264 + [_dataTaskDic removeObjectForKey:model.activityId];
  265 + [_downloadTaskDic removeObjectForKey:model.activityId];
  266 + }
  267 + }
  268 + }
  269 +}
  270 +
  271 +#pragma mark - 开始下载等待任务
  272 +- (void)startDownloadWaitingTask
  273 +{
  274 + self.isloading = NO;
  275 + if ((_currentCount < _maxConcurrentCount) && [self networkingAllowsDownloadTask]) {
  276 + // 获取下一条等待的数据
  277 + NSArray *array = [[CNLiveDataBaseManager shareManager] getAllWaitingData];
  278 + if (array.count > 0 && !self.isloading) {
  279 + [self getDownloadUrl:array[0]];
  280 + }
  281 + }
  282 +}
  283 +
  284 +#pragma mark - NSURLSessionDownloadDelegate
  285 +#pragma mark - 接收到服务器返回数据,会被调用多次
  286 +- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
  287 +{
  288 + // 获取模型
  289 + CNLiveAlbumAudioListModel *model = [[CNLiveDataBaseManager shareManager] getModelWithUrl:downloadTask.taskDescription];
  290 +
  291 + // 更新当前下载大小
  292 + model.tmpFileSize = (NSUInteger)totalBytesWritten;
  293 + model.totalFileSize = (NSUInteger)totalBytesExpectedToWrite;
  294 +
  295 + // 计算速度时间内下载文件的大小
  296 + model.intervalFileSize += (NSUInteger)bytesWritten;
  297 +
  298 + // 获取上次计算时间与当前时间间隔
  299 + NSInteger intervals = [CNLiveTimeTools getIntervalsWithTimeStamp:model.lastSpeedTime];
  300 + if (intervals >= 1) {
  301 + // 计算速度
  302 + model.speed = model.intervalFileSize / intervals;
  303 +
  304 + // 重置变量
  305 + model.intervalFileSize = 0;
  306 + model.lastSpeedTime = [CNLiveTimeTools getTimeStampWithDate:[NSDate date]];
  307 + }
  308 +
  309 + // 计算进度
  310 + model.progress = 1.0 * model.tmpFileSize / model.totalFileSize;
  311 +
  312 + // 更新数据库中数据
  313 + [[CNLiveDataBaseManager shareManager] updateWithModel:model option:CNDBUpdateOptionProgressData];
  314 +
  315 + // 进度通知
  316 + [[NSNotificationCenter defaultCenter] postNotificationName:WjjAudioDownloadProgressNotification object:model];
  317 +}
  318 +
  319 +#pragma mark - 下载完成
  320 +- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
  321 +{
  322 + // 获取模型
  323 + CNLiveAlbumAudioListModel *model = [[CNLiveDataBaseManager shareManager] getModelWithUrl:downloadTask.taskDescription];
  324 +
  325 + // 移动文件,原路径文件由系统自动删除
  326 + NSError *error = nil;
  327 + NSFileManager *fileManager = [NSFileManager defaultManager];
  328 + NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"albumAudioList_%@",model.albumId]];
  329 + if (![fileManager fileExistsAtPath:path]) {
  330 + [fileManager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];
  331 + }
  332 + if (!CNLiveStringIsEmpty(model.localPath)) {
  333 + [fileManager moveItemAtPath:[location path] toPath:model.localPath error:&error];
  334 + }
  335 + if (error) NSLog(@"下载完成,移动文件发生错误:%@ ---- %@", error,model.localPath);
  336 +}
  337 +
  338 +#pragma mark - NSURLSessionTaskDelegate
  339 +#pragma mark -请求完成
  340 +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
  341 +{
  342 + // 调用cancel方法直接返回,在相应操作是直接进行处理
  343 + if (error && [error.localizedDescription isEqualToString:@"cancelled"]) return;
  344 +
  345 + // 获取模型
  346 + CNLiveAlbumAudioListModel *model = [[CNLiveDataBaseManager shareManager] getModelWithUrl:task.taskDescription];
  347 +
  348 + // 下载时进程杀死,重新启动时回调错误
  349 + if (error && [error.userInfo objectForKey:NSURLErrorBackgroundTaskCancelledReasonKey]) {
  350 + model.state = CNDownloadStateWaiting;
  351 + model.resumeData = [error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData];
  352 + [[CNLiveDataBaseManager shareManager] updateWithModel:model option:CNDBUpdateOptionState | CNDBUpdateOptionResumeData];
  353 + return;
  354 + }
  355 + // 更新下载数据、任务状态
  356 + if (error) {
  357 + model.state = CNDownloadStateError;
  358 + model.resumeData = [error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData];
  359 + [[CNLiveDataBaseManager shareManager] updateWithModel:model option:CNDBUpdateOptionResumeData];
  360 +
  361 + }else {
  362 + model.state = CNDownloadStateFinish;
  363 + }
  364 +
  365 + // 更新数据
  366 + if (_currentCount > 0) _currentCount--;
  367 + if (!CNLiveStringIsEmpty(model.activityId)) {
  368 + [_dataTaskDic removeObjectForKey:model.activityId];
  369 + [_downloadTaskDic removeObjectForKey:model.activityId];
  370 + }
  371 + // 更新数据库状态
  372 + [[CNLiveDataBaseManager shareManager] updateWithModel:model option:CNDBUpdateOptionState];
  373 +
  374 + // 开启等待下载任务
  375 + [self startDownloadWaitingTask];
  376 + NSLog(@"\n 文件:%@,didCompleteWithError\n 本地路径:%@ \n 错误:%@ \n", model.title, model.localPath, error);
  377 +}
  378 +
  379 +#pragma mark - NSURLSessionDelegate
  380 +// 应用处于后台,所有下载任务完成及NSURLSession协议调用之后调用
  381 +//这个放在主工程delegate里实现
  382 +//- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
  383 +//{
  384 +//
  385 +// dispatch_async(dispatch_get_main_queue(), ^{
  386 +// AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
  387 +// if (appDelegate.backgroundSessionCompletionHandler) {
  388 +// void (^completionHandler)(void) = appDelegate.backgroundSessionCompletionHandler;
  389 +// appDelegate.backgroundSessionCompletionHandler = nil;
  390 +// // 执行block,系统后台生成快照,释放阻止应用挂起的断言
  391 +// completionHandler();
  392 +// }
  393 +// });
  394 +//}
  395 +
  396 +// 判断是否有网络和是否同意了4G
  397 +- (BOOL)networkingAllowsDownloadTask
  398 +{
  399 + // 当前网络状态
  400 + // 无网络 或 (当前为蜂窝网络,且不允许蜂窝网络下载)
  401 + if (![CNLiveNetworking isNetworking]&& !_allowsCellularAccess) {
  402 + return NO;
  403 + }
  404 + return YES;
  405 +
  406 +}
  407 +#pragma mark -添加网络通知
  408 +- (void)monitorTheNetwork {
  409 + __weak typeof(self) weakSelf = self;
  410 + [CNLiveDownloadManager networkStatusWithBlock:^(CNLiveNetworkStatusType status) {
  411 + switch (status) {
  412 + case CNLiveNetworkStatusNotReachable:{
  413 + NSLog(@"无网");
  414 + if ([[CNLiveDataBaseManager shareManager] getLastDownloadingModel]) {
  415 + [weakSelf pauseAllDownloadTask:YES];
  416 + weakSelf.isNohaveNet = YES; //还要考虑4G切换到wifi和wifi切换到4G
  417 + }
  418 + }
  419 + break;
  420 + case CNLiveNetworkStatusUnknown:{
  421 + NSLog(@"未知网络");
  422 + if ([[CNLiveDataBaseManager shareManager] getLastDownloadingModel]) {
  423 + [weakSelf pauseAllDownloadTask:YES];
  424 + weakSelf.isNohaveNet = YES;
  425 + }
  426 + }
  427 + break;
  428 + case CNLiveNetworkStatusReachableViaWiFi:{
  429 + NSLog(@"wifi");
  430 + if(weakSelf.isNohaveNet) {
  431 + [weakSelf startAllDownloadTask:YES];
  432 + }
  433 + }
  434 + break;
  435 + case CNLiveNetworkStatusReachableViaWWAN:{
  436 + NSLog(@"4G");
  437 + if (weakSelf.isNohaveNet && weakSelf.allowsCellularAccess ) {
  438 + [weakSelf startAllDownloadTask:YES];
  439 + }else {
  440 + if ([[CNLiveDataBaseManager shareManager] getLastDownloadingModel]) {
  441 + [weakSelf pauseAllDownloadTask:YES];
  442 + weakSelf.isNohaveNet = YES; //还要考虑4G切换到wifi和wifi切换到4G
  443 + [weakSelf showAlertView];
  444 + }
  445 + }
  446 + }
  447 + break;
  448 + default:
  449 + break;
  450 + }
  451 + }];
  452 +}
  453 +#pragma mark -IM连接成功通知
  454 +//- (void)IMConnectSucc {
  455 +// [self addDownloadReachabilityManager];
  456 +//}
  457 +#pragma mark -网络弹框
  458 +- (void)showAlertView {
  459 +
  460 + UIAlertView *alertView=[[UIAlertView alloc]initWithTitle:@"当前无Wifi,是否允许用流量继续下载" message:nil delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"继续下载", nil];
  461 + [alertView show];
  462 +}
  463 +
  464 +//监听点击事件 代理方法
  465 +- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
  466 +{
  467 + if (buttonIndex==0) {
  468 + NSLog(@"你点击了取消");
  469 + }
  470 + else if (buttonIndex==1) {
  471 + _allowsCellularAccess = YES;
  472 + [self startAllDownloadTask:YES];
  473 + }
  474 +}
  475 +
  476 +- (void)dealloc
  477 +{
  478 + [CNLiveDownloadManager removeNetworkStatue];
  479 + [_session invalidateAndCancel];
  480 + [[NSNotificationCenter defaultCenter] removeObserver:self];
  481 +}
  482 +
  483 +@end
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveMediaEditorNetworkManager.h 0 → 100644
  1 +//
  2 +// CNLiveMediaEditorNetworkManager.h
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/3.
  6 +//
  7 +
  8 +#import <Foundation/Foundation.h>
  9 +
  10 +NS_ASSUME_NONNULL_BEGIN
  11 +
  12 +@interface CNLiveMediaEditorNetworkManager : NSObject
  13 +/**
  14 + * 设置超时时间
  15 + */
  16 +@property (nonatomic, assign) NSTimeInterval timeoutInterval;
  17 +
  18 +/**
  19 + * 缓存策略
  20 + */
  21 +@property (nonatomic, assign) NSURLRequestCachePolicy cachePolicy;
  22 +
  23 ++ (nonnull CNLiveMediaEditorNetworkManager *)manager;
  24 +
  25 +/**
  26 + * GET 请求
  27 + * @param URL
  28 + * @param parameters 上传参数
  29 + * @param success 请求成功回调
  30 + * @param failure 请求失败回调
  31 + */
  32 +- (void)requestGetURL:(nullable NSString *)URL
  33 + parameters:(nullable NSDictionary *)parameters
  34 + success:(nullable void (^)(NSURLResponse *_Nullable response, id _Nullable responseObject))success
  35 + failure:(nullable void (^)(NSURLResponse *_Nullable response, NSError *_Nullable error))failure;
  36 +
  37 +/**
  38 + * POST 请求
  39 + * @param URL
  40 + * @param parameters 上传参数
  41 + * @param success 请求成功回调
  42 + * @param failure 请求失败回调
  43 + */
  44 +- (void)requestPostURL:(nullable NSString *)URL
  45 + parameters:(nullable NSDictionary *)parameters
  46 + success:(nullable void (^)(NSURLResponse *_Nullable response, id _Nullable responseObject))success
  47 + failure:(nullable void (^)(NSURLResponse *_Nullable response, NSError *_Nullable error))failure;
  48 +
  49 +
  50 +/**
  51 + * 用于获取播放地址
  52 + */
  53 +- (void)requestGetVideoURL:(nullable NSString *)URL
  54 + success:(nullable void (^)(NSString *_Nullable videoURL))success;
  55 +
  56 +
  57 +- (void)destroyNetManager;
  58 +@end
  59 +
  60 +NS_ASSUME_NONNULL_END
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveMediaEditorNetworkManager.m 0 → 100644
  1 +//
  2 +// CNLiveMediaEditorNetworkManager.m
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/3.
  6 +//
  7 +
  8 +#import "CNLiveMediaEditorNetworkManager.h"
  9 +#import "CNLiveMediaEditorRequestSerialization.h"
  10 +/**
  11 + * 网络超时时间 默认 60
  12 + */
  13 +static NSTimeInterval TimeoutInterval = 30.0 ;
  14 +
  15 +/**
  16 + * 缓存策略
  17 + * NSURLRequestUseProtocolCachePolicy // 默认的缓存策略(取决于协议)
  18 + * NSURLRequestReloadIgnoringLocalCacheData // 忽略缓存,重新请求
  19 + * NSURLRequestReloadIgnoringLocalAndRemoteCacheData // 未实现
  20 + * NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData // 忽略缓存,重新请求
  21 + * NSURLRequestReturnCacheDataElseLoad// 有缓存就用缓存,忽略过期时间!没有缓存就重新请求
  22 + * NSURLRequestReturnCacheDataDontLoad// 有缓存就用缓存,没有缓存就不发请求,当做请求出错处理(用于离线模式)
  23 + * NSURLRequestReloadRevalidatingCacheData // 未实现
  24 + */
  25 +static NSURLRequestCachePolicy CachePolicy = NSURLRequestUseProtocolCachePolicy;
  26 +
  27 +typedef void(^GetVideoURLSuccessBlock)(NSString *_Nullable videoURL);
  28 +
  29 +@interface CNLiveMediaEditorNetworkManager ()<NSURLSessionDelegate>
  30 +{
  31 + BOOL _result;
  32 +}
  33 +
  34 +@property (nonatomic, copy) GetVideoURLSuccessBlock successBlock;
  35 +
  36 +@end
  37 +
  38 +@implementation CNLiveMediaEditorNetworkManager
  39 +
  40 +- (void)dealloc
  41 +{
  42 + // D_NSLog(@">>>>>>>>>>>>>> CNLiveKSYNetworkManager dealloc");
  43 +}
  44 +
  45 +- (void)destroyNetManager {
  46 + self.successBlock = nil;
  47 + // D_NSLog(@">>>>>>>>>>>>>> destroyNetManager");
  48 +
  49 +}
  50 +
  51 ++ (CNLiveMediaEditorNetworkManager *)manager
  52 +{
  53 + static CNLiveMediaEditorNetworkManager *manager = nil;
  54 +
  55 + static dispatch_once_t predicate;
  56 +
  57 + dispatch_once(&predicate, ^{
  58 +
  59 + manager = [[CNLiveMediaEditorNetworkManager alloc] init];
  60 +
  61 + });
  62 +
  63 + manager.cachePolicy = CachePolicy;
  64 +
  65 + manager.timeoutInterval = TimeoutInterval;
  66 +
  67 + return manager;
  68 +}
  69 +
  70 +- (instancetype)init
  71 +{
  72 + self = [super init];
  73 + if (self) {
  74 + self.cachePolicy = CachePolicy;
  75 + self.timeoutInterval = TimeoutInterval;
  76 + }
  77 + return self;
  78 +}
  79 +
  80 +-(void)requestGetURL:(NSString *)URL
  81 + parameters:(NSDictionary *)parameters
  82 + success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success
  83 + failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure
  84 +{
  85 + NSURLSessionDataTask *task = [self dataTaskWithRequestMethod:@"GET" URLString:URL parameters:parameters success:success failure:failure];
  86 + [task resume];
  87 +}
  88 +
  89 +- (void)requestPostURL:(NSString *)URL
  90 + parameters:(NSDictionary *)parameters
  91 + success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success
  92 + failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure
  93 +{
  94 + NSURLSessionDataTask *task = [self dataTaskWithRequestMethod:@"POST" URLString:URL parameters:parameters success:success failure:failure];
  95 + [task resume];
  96 +}
  97 +
  98 +- (void)requestGetVideoURL:(NSString *)URL success:(void (^)(NSString * _Nullable))success {
  99 +
  100 + self.successBlock = success;
  101 + _result = NO;
  102 +
  103 + NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
  104 +
  105 + NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig
  106 + delegate:self
  107 + delegateQueue:[[NSOperationQueue alloc] init]];
  108 +
  109 + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:URL] cachePolicy:self.cachePolicy timeoutInterval:self.timeoutInterval];
  110 +
  111 + NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
  112 +
  113 + // 启动任务
  114 + [task resume];
  115 +}
  116 +
  117 +#pragma mark -
  118 +#pragma mark - NSURLSessionDelegate
  119 +// 1.接收到服务器的响应
  120 +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
  121 + // 允许处理服务器的响应,才会继续接收服务器返回的数据
  122 + completionHandler(NSURLSessionResponseCancel);
  123 + _result = YES;
  124 + self.successBlock([response.URL absoluteString]);
  125 +
  126 +}
  127 +
  128 +// 3.请求成功或者失败(如果失败,error有值)
  129 +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
  130 + // 请求完成,成功或者失败的处理
  131 +
  132 + if (_result) return;
  133 +
  134 + NSString *videoUrl302 = error.userInfo[@"NSErrorFailingURLStringKey"];
  135 + if (!videoUrl302 || ![videoUrl302 isKindOfClass:[NSString class]] || videoUrl302.length <= 0) {
  136 + videoUrl302 = nil;
  137 + }
  138 + self.successBlock(videoUrl302);
  139 +
  140 +}
  141 +
  142 +
  143 +- (NSURLSessionDataTask *)dataTaskWithRequestMethod:(NSString *)method
  144 + URLString:(NSString *)URLString
  145 + parameters:(NSDictionary *)parameters
  146 + success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success
  147 + failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure
  148 +{
  149 +
  150 + if (![URLString isKindOfClass:[NSString class]]) {
  151 + NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:@{NSLocalizedDescriptionKey : @"please enter a valid url"}];
  152 + failure(nil, error);
  153 + return nil;
  154 + }
  155 +
  156 + NSString *newURLString;
  157 + if ([method isEqualToString:@"GET"]) {
  158 + if (parameters) {
  159 + newURLString = [[URLString stringByAppendingString:@"?"] stringByAppendingString:[CNLiveMediaEditorRequestSerialization CNNetPlusQueryStringFromParameters:parameters]];
  160 + }else{
  161 + newURLString = URLString;
  162 + }
  163 + }else{
  164 + newURLString = URLString;
  165 + }
  166 +
  167 + NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:newURLString] cachePolicy:self.cachePolicy timeoutInterval:self.timeoutInterval];
  168 +
  169 + request.HTTPMethod = method;
  170 +
  171 + if([method isEqual:@"POST"]){
  172 + [request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
  173 + request.HTTPBody =[[CNLiveMediaEditorRequestSerialization CNNetPlusQueryStringFromParameters:parameters] dataUsingEncoding:NSUTF8StringEncoding];
  174 + }
  175 +
  176 + NSURLSessionDataTask *task = [self dataTaskWithRequest:request success:success failure:failure];
  177 +
  178 + return task;
  179 +}
  180 +
  181 +- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
  182 + success:(void (^)(NSURLResponse * _Nullable, id _Nullable))success
  183 + failure:(void (^)(NSURLResponse * _Nullable, NSError * _Nullable))failure
  184 +{
  185 + NSURLSession *session = [NSURLSession sharedSession];
  186 + NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
  187 +
  188 + dispatch_async(dispatch_get_main_queue(), ^{
  189 + if (error) {
  190 + failure(response,error);
  191 + }else{
  192 + if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
  193 + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
  194 + if (httpResponse.statusCode < 400) {
  195 + id jsonObj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
  196 + success(httpResponse,jsonObj);
  197 + } else {
  198 + NSError *failureError = [NSError errorWithDomain:NSURLErrorDomain code:httpResponse.statusCode userInfo:httpResponse.allHeaderFields];
  199 + failure(httpResponse,failureError);
  200 + }
  201 + } else {
  202 + failure(response,error);
  203 + }
  204 + }
  205 + });
  206 + }];
  207 +
  208 + return task;
  209 +}
  210 +
  211 +- (NSURL *)formatURLString:(NSString *)url
  212 +{
  213 + NSURL *urlString = [NSURL URLWithString:[url stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
  214 + return urlString;
  215 +}
  216 +
  217 +@end
  218 +
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveMediaEditorRequestSerialization.h 0 → 100644
  1 +//
  2 +// CNLiveMediaEditorRequestSerialization.h
  3 +// CNLiveBaseKit
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/3.
  6 +//
  7 +
  8 +#import <Foundation/Foundation.h>
  9 +
  10 +NS_ASSUME_NONNULL_BEGIN
  11 +
  12 +@interface CNLiveMediaEditorRequestSerialization : NSObject
  13 ++ (nullable NSString *)CNNetPlusQueryStringFromParameters:(nullable NSDictionary *)parameters;
  14 +@end
  15 +
  16 +NS_ASSUME_NONNULL_END
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveMediaEditorRequestSerialization.m 0 → 100644
  1 +//
  2 +// CNLiveMediaEditorRequestSerialization.m
  3 +// CNLiveBaseKit
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/3.
  6 +//
  7 +
  8 +#import "CNLiveMediaEditorRequestSerialization.h"
  9 +
  10 +@interface CNLiveMediaEditorRequestSerialization ()
  11 +@property (readwrite, nonatomic, strong) id value;
  12 +
  13 +@property (readwrite, nonatomic, strong) id field;
  14 +@end
  15 +
  16 +@implementation CNLiveMediaEditorRequestSerialization
  17 +- (id)initWithField:(id)field value:(id)value
  18 +{
  19 + self = [super init];
  20 +
  21 + if (self) {
  22 +
  23 + self.field = field;
  24 +
  25 + self.value = value;
  26 + }
  27 +
  28 + return self;
  29 +
  30 +}
  31 +#pragma mark -
  32 +
  33 +FOUNDATION_EXPORT NSArray * CNNetPlusQueryStringPairsFromDictionary(NSDictionary *dictionary);
  34 +FOUNDATION_EXPORT NSArray * CNNetPlusQueryStringPairsFromKeyAndValue(NSString *key, id value);
  35 +
  36 ++ (NSString *)CNNetPlusQueryStringFromParameters:(NSDictionary *)parameters
  37 +{
  38 + NSMutableArray *mutablePairs = [NSMutableArray array];
  39 + for (CNLiveMediaEditorRequestSerialization *pair in CNNetPlusQueryStringPairsFromDictionary(parameters)) {
  40 + [mutablePairs addObject:[pair URLEncodedStringValue]];
  41 + }
  42 + return [mutablePairs componentsJoinedByString:@"&"];
  43 +}
  44 +
  45 +NSArray * CNNetPlusQueryStringPairsFromDictionary(NSDictionary *dictionary)
  46 +{
  47 + return CNNetPlusQueryStringPairsFromKeyAndValue(nil, dictionary);
  48 +}
  49 +
  50 +/**
  51 + * 处理上传参数
  52 + */
  53 +NSArray * CNNetPlusQueryStringPairsFromKeyAndValue(NSString *key, id value)
  54 +{
  55 + NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
  56 +
  57 + //排序方式
  58 + NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
  59 +
  60 + if ([value isKindOfClass:[NSDictionary class]]) { //字典
  61 + NSDictionary *dictionary = value;
  62 + for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[sortDescriptor]]) {
  63 + id nestedValue = dictionary[nestedKey];
  64 + if (nestedKey) {
  65 + [mutableQueryStringComponents addObjectsFromArray:CNNetPlusQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
  66 + }
  67 + }
  68 + }
  69 +
  70 + else if ([value isKindOfClass:[NSArray class]]){ //数组
  71 + NSArray *array = value;
  72 + for (id nestedValue in array) {
  73 + [mutableQueryStringComponents addObjectsFromArray:CNNetPlusQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
  74 + }
  75 + }else if ([value isKindOfClass:[NSSet class]]){ //集合
  76 + NSSet *set = value;
  77 + for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
  78 + [mutableQueryStringComponents addObjectsFromArray:CNNetPlusQueryStringPairsFromKeyAndValue(key, obj)];
  79 + }
  80 + }else{ //其他类型
  81 + [mutableQueryStringComponents addObject:[[CNLiveMediaEditorRequestSerialization alloc] initWithField:key value:value]];
  82 + }
  83 +
  84 + return mutableQueryStringComponents;
  85 +}
  86 +
  87 +static NSString * CNNetPlusPercentEscapedStringFromString(NSString *string) {
  88 + static NSString * const kCNNetPlusCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
  89 + static NSString * const kCNNetPlusCharactersSubDelimitersToEncode = @"!$&'()*+,;=";
  90 +
  91 + NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
  92 + [allowedCharacterSet removeCharactersInString:[kCNNetPlusCharactersGeneralDelimitersToEncode stringByAppendingString:kCNNetPlusCharactersSubDelimitersToEncode]];
  93 +
  94 +
  95 + static NSUInteger const batchSize = 50;
  96 +
  97 + NSUInteger index = 0;
  98 + NSMutableString *escaped = @"".mutableCopy;
  99 +
  100 + while (index < string.length) {
  101 +#pragma GCC diagnostic push
  102 +#pragma GCC diagnostic ignored "-Wgnu"
  103 + NSUInteger length = MIN(string.length - index, batchSize);
  104 +#pragma GCC diagnostic pop
  105 + NSRange range = NSMakeRange(index, length);
  106 +
  107 + range = [string rangeOfComposedCharacterSequencesForRange:range];
  108 +
  109 + NSString *substring = [string substringWithRange:range];
  110 + NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
  111 + [escaped appendString:encoded];
  112 +
  113 + index += range.length;
  114 + }
  115 +
  116 + return escaped;
  117 +}
  118 +
  119 +- (NSString *)URLEncodedStringValue {
  120 + if (!self.value || [self.value isEqual:[NSNull null]]) {
  121 + return CNNetPlusPercentEscapedStringFromString([self.field description]);
  122 + } else {
  123 + return [NSString stringWithFormat:@"%@=%@", CNNetPlusPercentEscapedStringFromString([self.field description]), CNNetPlusPercentEscapedStringFromString([self.value description])];
  124 + }
  125 +}
  126 +
  127 +@end
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveVodUrlUtil.h 0 → 100644
  1 +//
  2 +// CNLiveVodUrlUtil.h
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/3.
  6 +//
  7 +
  8 +#import <Foundation/Foundation.h>
  9 +
  10 +NS_ASSUME_NONNULL_BEGIN
  11 +
  12 +@interface CNLiveVodUrlUtil : NSObject
  13 ++ (instancetype)manager;
  14 +
  15 +/**
  16 + 获取点播内容url
  17 +
  18 + @param vId 内容id
  19 + @param channelName 频道名称
  20 + @param sid UserId
  21 + @param playType 音频:"a" 视频:"v"
  22 + @param tag 非必传
  23 + @param completeBlock 回调
  24 + */
  25 +- (void)getVodUrlWithVid:(NSString *)vId channelName:(NSString *)channelName sid:(NSString *)sid playType:(NSString *)playType tag:(NSString *)tag completeBlock:(void(^)(NSString *vodUrl))completeBlock;
  26 +@end
  27 +
  28 +NS_ASSUME_NONNULL_END
... ...
CNLiveDownloadManager/Classes/ViewModel/CNLiveVodUrlUtil.m 0 → 100644
  1 +//
  2 +// CNLiveVodUrlUtil.m
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/3.
  6 +//
  7 +
  8 +#import "CNLiveVodUrlUtil.h"
  9 +#import "CNLiveMediaEditorNetworkManager.h"
  10 +#import "CNEnvironmentHeader.h"
  11 +#import "CNLiveBusinessTools.h"
  12 +#import "NetworkAPIs.h"
  13 +@implementation CNLiveVodUrlUtil
  14 ++ (instancetype)manager {
  15 + static CNLiveVodUrlUtil *instance = nil;
  16 + static dispatch_once_t onceToken;
  17 +
  18 + dispatch_once(&onceToken, ^{
  19 + instance = [[self alloc] init];
  20 + });
  21 + return instance;
  22 +}
  23 +
  24 +- (void)getVodUrlWithVid:(NSString *)vId channelName:(NSString *)channelName sid:(NSString *)sid playType:(NSString *)playType tag:(NSString *)tag completeBlock:(void(^)(NSString *vodUrl))completeBlock
  25 +{
  26 + NSInteger time = [[NSDate date] timeIntervalSince1970];
  27 + NSString *timeString = [NSString stringWithFormat:@"%ld", (long)time];
  28 +
  29 + NSString *timestamp = timeString;
  30 + NSString *appId = AppId;
  31 +
  32 + NSString *uid = [CNLiveBusinessTools getUidForStat:timestamp];
  33 + ////playType @"a": @"v"
  34 + ////
  35 + NSDictionary *parameter1 = @{@"appId": appId,
  36 + @"vId": vId?vId:@"",
  37 + @"timestamp": timestamp,
  38 + @"isHLS": @"1",
  39 + @"plat": @"i",
  40 + @"playType": playType ? playType: @"",
  41 + @"platform_id": [NSBundle mainBundle].bundleIdentifier,
  42 + @"channelName": channelName?channelName:@"",
  43 + @"tag": tag?tag:@"",
  44 + @"from": @"apple", @"sid":sid?sid:@"",
  45 + @"uid": uid?uid:@""};
  46 +
  47 + NSString *string1 = [NSString stringWithFormat:@"%@&key=%@", [CNLiveBusinessTools signvalue:parameter1], APPKey];
  48 + NSString *signString1 = [[CNLiveBusinessTools sha1:string1] uppercaseString];
  49 +
  50 + NSString *videourl1 = [NSString stringWithFormat:@"%@?%@&sign=%@", CNGetVodUrl, [CNLiveBusinessTools signvalue:parameter1], signString1];
  51 +
  52 + CNLiveMediaEditorNetworkManager *manager = [[CNLiveMediaEditorNetworkManager alloc] init];
  53 +
  54 + [manager requestGetVideoURL:videourl1 success:^(NSString * _Nullable videoURL) {
  55 + dispatch_async(dispatch_get_main_queue(), ^{
  56 + if (completeBlock) {
  57 + completeBlock(videoURL);
  58 + }
  59 + });
  60 + }];
  61 +}
  62 +
  63 +@end
... ...
CNLiveDownloadManager/Classes/ViewModel/NSURLSession+CNLiveCorrectedResumeData.h 0 → 100644
  1 +//
  2 +// NSURLSession+CNLiveCorrectedResumeData.h
  3 +// CNLiveBaseKit
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/3.
  6 +//
  7 +
  8 +
  9 +
  10 +NS_ASSUME_NONNULL_BEGIN
  11 +
  12 +@interface NSURLSession (CNLiveCorrectedResumeData)
  13 +- (NSURLSessionDownloadTask *)downloadTaskWithCorrectResumeData:(NSData *)resumeData;
  14 +@end
  15 +
  16 +NS_ASSUME_NONNULL_END
... ...
CNLiveDownloadManager/Classes/ViewModel/NSURLSession+CNLiveCorrectedResumeData.m 0 → 100644
  1 +//
  2 +// NSURLSession+CNLiveCorrectedResumeData.m
  3 +// CNLiveBaseKit
  4 +//
  5 +// Created by 殷巧娟 on 2019/6/3.
  6 +//
  7 +
  8 +#import "NSURLSession+CNLiveCorrectedResumeData.h"
  9 +static NSString *const resumeCurrentRequest = @"NSURLSessionResumeCurrentRequest";
  10 +static NSString *const resumeOriginalRequest = @"NSURLSessionResumeOriginalRequest";
  11 +@implementation NSURLSession (CNLiveCorrectedResumeData)
  12 +- (NSURLSessionDownloadTask *)downloadTaskWithCorrectResumeData:(NSData *)resumeData
  13 +{
  14 + NSData *data = [self getCorrectResumeDataWithData:resumeData];
  15 + data = data ? data : resumeData;
  16 + NSURLSessionDownloadTask *task = [self downloadTaskWithResumeData:data];
  17 + NSMutableDictionary *resumeDic = [self getResumeDictionaryWithData:data];
  18 +
  19 + if (resumeDic) {
  20 + if (!task.originalRequest) {
  21 + NSData *originalReqData = resumeDic[resumeOriginalRequest];
  22 + NSURLRequest *originalRequest = [NSKeyedUnarchiver unarchiveObjectWithData:originalReqData];
  23 + if (originalRequest) [task setValue:originalRequest forKey:@"originalRequest"];
  24 + }
  25 + if (!task.currentRequest) {
  26 + NSData *currentReqData = resumeDic[resumeCurrentRequest];
  27 + NSURLRequest *currentRequest = [NSKeyedUnarchiver unarchiveObjectWithData:currentReqData];
  28 + if (currentRequest) [task setValue:currentRequest forKey:@"currentRequest"];
  29 + }
  30 + }
  31 +
  32 + return task;
  33 +}
  34 +
  35 +- (NSData *)getCorrectResumeDataWithData:(NSData *)data
  36 +{
  37 + if (!data) return nil;
  38 +
  39 + NSMutableDictionary *resumeDictionary = [self getResumeDictionaryWithData:data];
  40 + if (!resumeDictionary) return nil;
  41 +
  42 + resumeDictionary[resumeCurrentRequest] = [self getCorrectRequestDataWithData:resumeDictionary[resumeCurrentRequest]];
  43 + resumeDictionary[resumeOriginalRequest] = [self getCorrectRequestDataWithData:resumeDictionary[resumeOriginalRequest]];
  44 +
  45 + return [NSPropertyListSerialization dataWithPropertyList:resumeDictionary format:NSPropertyListXMLFormat_v1_0 options:0 error:nil];
  46 +}
  47 +
  48 +- (NSMutableDictionary *)getResumeDictionaryWithData:(NSData *)data
  49 +{
  50 + return [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:nil error:nil];
  51 +}
  52 +
  53 +- (NSData *)getCorrectRequestDataWithData:(NSData *)data
  54 +{
  55 + if (!data) return nil;
  56 +
  57 + if ([NSKeyedUnarchiver unarchiveObjectWithData:data]) return data;
  58 +
  59 + NSMutableDictionary *archive = [[NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:nil error:nil] mutableCopy];
  60 + if (!archive) return nil;
  61 +
  62 + NSInteger i = 0;
  63 + id objectss = archive[@"$objects"];
  64 + while ([objectss[1] objectForKey:[NSString stringWithFormat:@"$%ld", i]]) {
  65 + i++;
  66 + }
  67 +
  68 + NSInteger j = 0;
  69 + while ([archive[@"$objects"][1] objectForKey:[NSString stringWithFormat:@"__nsurlrequest_proto_prop_obj_%ld", j]]) {
  70 + NSMutableArray *array = archive[@"$objects"];
  71 + NSMutableDictionary *dic = array[1];
  72 + id obj = [dic objectForKey:[NSString stringWithFormat:@"__nsurlrequest_proto_prop_obj_%ld", j]];
  73 + if (obj) {
  74 + [dic setValue:obj forKey:[NSString stringWithFormat:@"$%ld", i + j]];
  75 + [dic removeObjectForKey:[NSString stringWithFormat:@"__nsurlrequest_proto_prop_obj_%ld", j]];
  76 + [array replaceObjectAtIndex:1 withObject:dic];
  77 + archive[@"$objects"] = array;
  78 + }
  79 + j++;
  80 + }
  81 +
  82 + if ([archive[@"$objects"][1] objectForKey:@"__nsurlrequest_proto_props"]) {
  83 + NSMutableArray *array = archive[@"$objects"];
  84 + NSMutableDictionary *dic = array[1];
  85 + id obj = [dic objectForKey:@"__nsurlrequest_proto_props"];
  86 + if (obj) {
  87 + [dic setValue:obj forKey:[NSString stringWithFormat:@"$%ld", i + j]];
  88 + [dic removeObjectForKey:@"__nsurlrequest_proto_props"];
  89 + [array replaceObjectAtIndex:1 withObject:dic];
  90 + archive[@"$objects"] = array;
  91 + }
  92 + }
  93 +
  94 + if ([archive[@"$top"] objectForKey:@"NSKeyedArchiveRootObjectKey"]) {
  95 + [archive[@"$top"] setObject:archive[@"$top"][@"NSKeyedArchiveRootObjectKey"] forKey: NSKeyedArchiveRootObjectKey];
  96 + [archive[@"$top"] removeObjectForKey:@"NSKeyedArchiveRootObjectKey"];
  97 + }
  98 +
  99 + return [NSPropertyListSerialization dataWithPropertyList:archive format:NSPropertyListBinaryFormat_v1_0 options:0 error:nil];
  100 +}
  101 +@end
... ...
Example/CNLiveDownloadManager.xcodeproj/project.pbxproj 0 → 100644
  1 +// !$*UTF8*$!
  2 +{
  3 + archiveVersion = 1;
  4 + classes = {
  5 + };
  6 + objectVersion = 46;
  7 + objects = {
  8 +
  9 +/* Begin PBXBuildFile section */
  10 + 3A484E3A8C834C0D7D28435D /* Pods_CNLiveDownloadManager_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 94E0BBF4750718BCFD83CAE0 /* Pods_CNLiveDownloadManager_Example.framework */; };
  11 + 412D189855F76D0811C34BFE /* Pods_CNLiveDownloadManager_Tests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E3D7A50D9FAB850D3C44A064 /* Pods_CNLiveDownloadManager_Tests.framework */; };
  12 + 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
  13 + 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58F195388D20070C39A /* CoreGraphics.framework */; };
  14 + 6003F592195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
  15 + 6003F598195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F596195388D20070C39A /* InfoPlist.strings */; };
  16 + 6003F59A195388D20070C39A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F599195388D20070C39A /* main.m */; };
  17 + 6003F59E195388D20070C39A /* CNLiveAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */; };
  18 + 6003F5A7195388D20070C39A /* CNLiveViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5A6195388D20070C39A /* CNLiveViewController.m */; };
  19 + 6003F5A9195388D20070C39A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5A8195388D20070C39A /* Images.xcassets */; };
  20 + 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F5AF195388D20070C39A /* XCTest.framework */; };
  21 + 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F58D195388D20070C39A /* Foundation.framework */; };
  22 + 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6003F591195388D20070C39A /* UIKit.framework */; };
  23 + 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6003F5B8195388D20070C39A /* InfoPlist.strings */; };
  24 + 6003F5BC195388D20070C39A /* Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 6003F5BB195388D20070C39A /* Tests.m */; };
  25 + 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */; };
  26 + 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */; };
  27 +/* End PBXBuildFile section */
  28 +
  29 +/* Begin PBXContainerItemProxy section */
  30 + 6003F5B3195388D20070C39A /* PBXContainerItemProxy */ = {
  31 + isa = PBXContainerItemProxy;
  32 + containerPortal = 6003F582195388D10070C39A /* Project object */;
  33 + proxyType = 1;
  34 + remoteGlobalIDString = 6003F589195388D20070C39A;
  35 + remoteInfo = CNLiveDownloadManager;
  36 + };
  37 +/* End PBXContainerItemProxy section */
  38 +
  39 +/* Begin PBXFileReference section */
  40 + 25F58E15CCB760285426BA4B /* CNLiveDownloadManager.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = CNLiveDownloadManager.podspec; path = ../CNLiveDownloadManager.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
  41 + 4E591664CF796F923B830DF3 /* Pods-CNLiveDownloadManager_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLiveDownloadManager_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-CNLiveDownloadManager_Example/Pods-CNLiveDownloadManager_Example.release.xcconfig"; sourceTree = "<group>"; };
  42 + 56C6C35211FE6387AC196F94 /* Pods-CNLiveDownloadManager_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLiveDownloadManager_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CNLiveDownloadManager_Example/Pods-CNLiveDownloadManager_Example.debug.xcconfig"; sourceTree = "<group>"; };
  43 + 6003F58A195388D20070C39A /* CNLiveDownloadManager_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CNLiveDownloadManager_Example.app; sourceTree = BUILT_PRODUCTS_DIR; };
  44 + 6003F58D195388D20070C39A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
  45 + 6003F58F195388D20070C39A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
  46 + 6003F591195388D20070C39A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
  47 + 6003F595195388D20070C39A /* CNLiveDownloadManager-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "CNLiveDownloadManager-Info.plist"; sourceTree = "<group>"; };
  48 + 6003F597195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
  49 + 6003F599195388D20070C39A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
  50 + 6003F59B195388D20070C39A /* CNLiveDownloadManager-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CNLiveDownloadManager-Prefix.pch"; sourceTree = "<group>"; };
  51 + 6003F59C195388D20070C39A /* CNLiveAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNLiveAppDelegate.h; sourceTree = "<group>"; };
  52 + 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CNLiveAppDelegate.m; sourceTree = "<group>"; };
  53 + 6003F5A5195388D20070C39A /* CNLiveViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CNLiveViewController.h; sourceTree = "<group>"; };
  54 + 6003F5A6195388D20070C39A /* CNLiveViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CNLiveViewController.m; sourceTree = "<group>"; };
  55 + 6003F5A8195388D20070C39A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
  56 + 6003F5AE195388D20070C39A /* CNLiveDownloadManager_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CNLiveDownloadManager_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
  57 + 6003F5AF195388D20070C39A /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
  58 + 6003F5B7195388D20070C39A /* Tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Tests-Info.plist"; sourceTree = "<group>"; };
  59 + 6003F5B9195388D20070C39A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
  60 + 6003F5BB195388D20070C39A /* Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Tests.m; sourceTree = "<group>"; };
  61 + 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tests-Prefix.pch"; sourceTree = "<group>"; };
  62 + 71719F9E1E33DC2100824A3D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
  63 + 72041DDD913A10D596ECFEEE /* Pods-CNLiveDownloadManager_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLiveDownloadManager_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-CNLiveDownloadManager_Tests/Pods-CNLiveDownloadManager_Tests.debug.xcconfig"; sourceTree = "<group>"; };
  64 + 82FC0100889995D212B4E376 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
  65 + 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = Main.storyboard; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
  66 + 94E0BBF4750718BCFD83CAE0 /* Pods_CNLiveDownloadManager_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CNLiveDownloadManager_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
  67 + BF5F74A07CE41BEC53E597F0 /* Pods-CNLiveDownloadManager_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-CNLiveDownloadManager_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-CNLiveDownloadManager_Tests/Pods-CNLiveDownloadManager_Tests.release.xcconfig"; sourceTree = "<group>"; };
  68 + CEE8B05CD80963DD46D613E0 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
  69 + E3D7A50D9FAB850D3C44A064 /* Pods_CNLiveDownloadManager_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_CNLiveDownloadManager_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
  70 +/* End PBXFileReference section */
  71 +
  72 +/* Begin PBXFrameworksBuildPhase section */
  73 + 6003F587195388D20070C39A /* Frameworks */ = {
  74 + isa = PBXFrameworksBuildPhase;
  75 + buildActionMask = 2147483647;
  76 + files = (
  77 + 6003F590195388D20070C39A /* CoreGraphics.framework in Frameworks */,
  78 + 6003F592195388D20070C39A /* UIKit.framework in Frameworks */,
  79 + 6003F58E195388D20070C39A /* Foundation.framework in Frameworks */,
  80 + 3A484E3A8C834C0D7D28435D /* Pods_CNLiveDownloadManager_Example.framework in Frameworks */,
  81 + );
  82 + runOnlyForDeploymentPostprocessing = 0;
  83 + };
  84 + 6003F5AB195388D20070C39A /* Frameworks */ = {
  85 + isa = PBXFrameworksBuildPhase;
  86 + buildActionMask = 2147483647;
  87 + files = (
  88 + 6003F5B0195388D20070C39A /* XCTest.framework in Frameworks */,
  89 + 6003F5B2195388D20070C39A /* UIKit.framework in Frameworks */,
  90 + 6003F5B1195388D20070C39A /* Foundation.framework in Frameworks */,
  91 + 412D189855F76D0811C34BFE /* Pods_CNLiveDownloadManager_Tests.framework in Frameworks */,
  92 + );
  93 + runOnlyForDeploymentPostprocessing = 0;
  94 + };
  95 +/* End PBXFrameworksBuildPhase section */
  96 +
  97 +/* Begin PBXGroup section */
  98 + 19D326128EE4D599D6324204 /* Pods */ = {
  99 + isa = PBXGroup;
  100 + children = (
  101 + 56C6C35211FE6387AC196F94 /* Pods-CNLiveDownloadManager_Example.debug.xcconfig */,
  102 + 4E591664CF796F923B830DF3 /* Pods-CNLiveDownloadManager_Example.release.xcconfig */,
  103 + 72041DDD913A10D596ECFEEE /* Pods-CNLiveDownloadManager_Tests.debug.xcconfig */,
  104 + BF5F74A07CE41BEC53E597F0 /* Pods-CNLiveDownloadManager_Tests.release.xcconfig */,
  105 + );
  106 + name = Pods;
  107 + sourceTree = "<group>";
  108 + };
  109 + 6003F581195388D10070C39A = {
  110 + isa = PBXGroup;
  111 + children = (
  112 + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */,
  113 + 6003F593195388D20070C39A /* Example for CNLiveDownloadManager */,
  114 + 6003F5B5195388D20070C39A /* Tests */,
  115 + 6003F58C195388D20070C39A /* Frameworks */,
  116 + 6003F58B195388D20070C39A /* Products */,
  117 + 19D326128EE4D599D6324204 /* Pods */,
  118 + );
  119 + sourceTree = "<group>";
  120 + };
  121 + 6003F58B195388D20070C39A /* Products */ = {
  122 + isa = PBXGroup;
  123 + children = (
  124 + 6003F58A195388D20070C39A /* CNLiveDownloadManager_Example.app */,
  125 + 6003F5AE195388D20070C39A /* CNLiveDownloadManager_Tests.xctest */,
  126 + );
  127 + name = Products;
  128 + sourceTree = "<group>";
  129 + };
  130 + 6003F58C195388D20070C39A /* Frameworks */ = {
  131 + isa = PBXGroup;
  132 + children = (
  133 + 6003F58D195388D20070C39A /* Foundation.framework */,
  134 + 6003F58F195388D20070C39A /* CoreGraphics.framework */,
  135 + 6003F591195388D20070C39A /* UIKit.framework */,
  136 + 6003F5AF195388D20070C39A /* XCTest.framework */,
  137 + 94E0BBF4750718BCFD83CAE0 /* Pods_CNLiveDownloadManager_Example.framework */,
  138 + E3D7A50D9FAB850D3C44A064 /* Pods_CNLiveDownloadManager_Tests.framework */,
  139 + );
  140 + name = Frameworks;
  141 + sourceTree = "<group>";
  142 + };
  143 + 6003F593195388D20070C39A /* Example for CNLiveDownloadManager */ = {
  144 + isa = PBXGroup;
  145 + children = (
  146 + 6003F59C195388D20070C39A /* CNLiveAppDelegate.h */,
  147 + 6003F59D195388D20070C39A /* CNLiveAppDelegate.m */,
  148 + 873B8AEA1B1F5CCA007FD442 /* Main.storyboard */,
  149 + 6003F5A5195388D20070C39A /* CNLiveViewController.h */,
  150 + 6003F5A6195388D20070C39A /* CNLiveViewController.m */,
  151 + 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */,
  152 + 6003F5A8195388D20070C39A /* Images.xcassets */,
  153 + 6003F594195388D20070C39A /* Supporting Files */,
  154 + );
  155 + name = "Example for CNLiveDownloadManager";
  156 + path = CNLiveDownloadManager;
  157 + sourceTree = "<group>";
  158 + };
  159 + 6003F594195388D20070C39A /* Supporting Files */ = {
  160 + isa = PBXGroup;
  161 + children = (
  162 + 6003F595195388D20070C39A /* CNLiveDownloadManager-Info.plist */,
  163 + 6003F596195388D20070C39A /* InfoPlist.strings */,
  164 + 6003F599195388D20070C39A /* main.m */,
  165 + 6003F59B195388D20070C39A /* CNLiveDownloadManager-Prefix.pch */,
  166 + );
  167 + name = "Supporting Files";
  168 + sourceTree = "<group>";
  169 + };
  170 + 6003F5B5195388D20070C39A /* Tests */ = {
  171 + isa = PBXGroup;
  172 + children = (
  173 + 6003F5BB195388D20070C39A /* Tests.m */,
  174 + 6003F5B6195388D20070C39A /* Supporting Files */,
  175 + );
  176 + path = Tests;
  177 + sourceTree = "<group>";
  178 + };
  179 + 6003F5B6195388D20070C39A /* Supporting Files */ = {
  180 + isa = PBXGroup;
  181 + children = (
  182 + 6003F5B7195388D20070C39A /* Tests-Info.plist */,
  183 + 6003F5B8195388D20070C39A /* InfoPlist.strings */,
  184 + 606FC2411953D9B200FFA9A0 /* Tests-Prefix.pch */,
  185 + );
  186 + name = "Supporting Files";
  187 + sourceTree = "<group>";
  188 + };
  189 + 60FF7A9C1954A5C5007DD14C /* Podspec Metadata */ = {
  190 + isa = PBXGroup;
  191 + children = (
  192 + 25F58E15CCB760285426BA4B /* CNLiveDownloadManager.podspec */,
  193 + 82FC0100889995D212B4E376 /* README.md */,
  194 + CEE8B05CD80963DD46D613E0 /* LICENSE */,
  195 + );
  196 + name = "Podspec Metadata";
  197 + sourceTree = "<group>";
  198 + };
  199 +/* End PBXGroup section */
  200 +
  201 +/* Begin PBXNativeTarget section */
  202 + 6003F589195388D20070C39A /* CNLiveDownloadManager_Example */ = {
  203 + isa = PBXNativeTarget;
  204 + buildConfigurationList = 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLiveDownloadManager_Example" */;
  205 + buildPhases = (
  206 + 56D85D721C5939967106CB00 /* [CP] Check Pods Manifest.lock */,
  207 + 6003F586195388D20070C39A /* Sources */,
  208 + 6003F587195388D20070C39A /* Frameworks */,
  209 + 6003F588195388D20070C39A /* Resources */,
  210 + FD4AA0BF8DE86B4A432A5A0A /* [CP] Embed Pods Frameworks */,
  211 + );
  212 + buildRules = (
  213 + );
  214 + dependencies = (
  215 + );
  216 + name = CNLiveDownloadManager_Example;
  217 + productName = CNLiveDownloadManager;
  218 + productReference = 6003F58A195388D20070C39A /* CNLiveDownloadManager_Example.app */;
  219 + productType = "com.apple.product-type.application";
  220 + };
  221 + 6003F5AD195388D20070C39A /* CNLiveDownloadManager_Tests */ = {
  222 + isa = PBXNativeTarget;
  223 + buildConfigurationList = 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLiveDownloadManager_Tests" */;
  224 + buildPhases = (
  225 + 8E7E18814F68BFFC19474C88 /* [CP] Check Pods Manifest.lock */,
  226 + 6003F5AA195388D20070C39A /* Sources */,
  227 + 6003F5AB195388D20070C39A /* Frameworks */,
  228 + 6003F5AC195388D20070C39A /* Resources */,
  229 + B90EAAB187AC920C2FDA35C2 /* [CP] Embed Pods Frameworks */,
  230 + );
  231 + buildRules = (
  232 + );
  233 + dependencies = (
  234 + 6003F5B4195388D20070C39A /* PBXTargetDependency */,
  235 + );
  236 + name = CNLiveDownloadManager_Tests;
  237 + productName = CNLiveDownloadManagerTests;
  238 + productReference = 6003F5AE195388D20070C39A /* CNLiveDownloadManager_Tests.xctest */;
  239 + productType = "com.apple.product-type.bundle.unit-test";
  240 + };
  241 +/* End PBXNativeTarget section */
  242 +
  243 +/* Begin PBXProject section */
  244 + 6003F582195388D10070C39A /* Project object */ = {
  245 + isa = PBXProject;
  246 + attributes = {
  247 + CLASSPREFIX = CNLive;
  248 + LastUpgradeCheck = 0720;
  249 + ORGANIZATIONNAME = "殷巧娟";
  250 + TargetAttributes = {
  251 + 6003F589195388D20070C39A = {
  252 + DevelopmentTeam = 94X49GG3ZW;
  253 + };
  254 + 6003F5AD195388D20070C39A = {
  255 + TestTargetID = 6003F589195388D20070C39A;
  256 + };
  257 + };
  258 + };
  259 + buildConfigurationList = 6003F585195388D10070C39A /* Build configuration list for PBXProject "CNLiveDownloadManager" */;
  260 + compatibilityVersion = "Xcode 3.2";
  261 + developmentRegion = English;
  262 + hasScannedForEncodings = 0;
  263 + knownRegions = (
  264 + en,
  265 + Base,
  266 + );
  267 + mainGroup = 6003F581195388D10070C39A;
  268 + productRefGroup = 6003F58B195388D20070C39A /* Products */;
  269 + projectDirPath = "";
  270 + projectRoot = "";
  271 + targets = (
  272 + 6003F589195388D20070C39A /* CNLiveDownloadManager_Example */,
  273 + 6003F5AD195388D20070C39A /* CNLiveDownloadManager_Tests */,
  274 + );
  275 + };
  276 +/* End PBXProject section */
  277 +
  278 +/* Begin PBXResourcesBuildPhase section */
  279 + 6003F588195388D20070C39A /* Resources */ = {
  280 + isa = PBXResourcesBuildPhase;
  281 + buildActionMask = 2147483647;
  282 + files = (
  283 + 873B8AEB1B1F5CCA007FD442 /* Main.storyboard in Resources */,
  284 + 71719F9F1E33DC2100824A3D /* LaunchScreen.storyboard in Resources */,
  285 + 6003F5A9195388D20070C39A /* Images.xcassets in Resources */,
  286 + 6003F598195388D20070C39A /* InfoPlist.strings in Resources */,
  287 + );
  288 + runOnlyForDeploymentPostprocessing = 0;
  289 + };
  290 + 6003F5AC195388D20070C39A /* Resources */ = {
  291 + isa = PBXResourcesBuildPhase;
  292 + buildActionMask = 2147483647;
  293 + files = (
  294 + 6003F5BA195388D20070C39A /* InfoPlist.strings in Resources */,
  295 + );
  296 + runOnlyForDeploymentPostprocessing = 0;
  297 + };
  298 +/* End PBXResourcesBuildPhase section */
  299 +
  300 +/* Begin PBXShellScriptBuildPhase section */
  301 + 56D85D721C5939967106CB00 /* [CP] Check Pods Manifest.lock */ = {
  302 + isa = PBXShellScriptBuildPhase;
  303 + buildActionMask = 2147483647;
  304 + files = (
  305 + );
  306 + inputFileListPaths = (
  307 + );
  308 + inputPaths = (
  309 + "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
  310 + "${PODS_ROOT}/Manifest.lock",
  311 + );
  312 + name = "[CP] Check Pods Manifest.lock";
  313 + outputFileListPaths = (
  314 + );
  315 + outputPaths = (
  316 + "$(DERIVED_FILE_DIR)/Pods-CNLiveDownloadManager_Example-checkManifestLockResult.txt",
  317 + );
  318 + runOnlyForDeploymentPostprocessing = 0;
  319 + shellPath = /bin/sh;
  320 + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
  321 + showEnvVarsInLog = 0;
  322 + };
  323 + 8E7E18814F68BFFC19474C88 /* [CP] Check Pods Manifest.lock */ = {
  324 + isa = PBXShellScriptBuildPhase;
  325 + buildActionMask = 2147483647;
  326 + files = (
  327 + );
  328 + inputFileListPaths = (
  329 + );
  330 + inputPaths = (
  331 + "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
  332 + "${PODS_ROOT}/Manifest.lock",
  333 + );
  334 + name = "[CP] Check Pods Manifest.lock";
  335 + outputFileListPaths = (
  336 + );
  337 + outputPaths = (
  338 + "$(DERIVED_FILE_DIR)/Pods-CNLiveDownloadManager_Tests-checkManifestLockResult.txt",
  339 + );
  340 + runOnlyForDeploymentPostprocessing = 0;
  341 + shellPath = /bin/sh;
  342 + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
  343 + showEnvVarsInLog = 0;
  344 + };
  345 + B90EAAB187AC920C2FDA35C2 /* [CP] Embed Pods Frameworks */ = {
  346 + isa = PBXShellScriptBuildPhase;
  347 + buildActionMask = 2147483647;
  348 + files = (
  349 + );
  350 + inputFileListPaths = (
  351 + );
  352 + inputPaths = (
  353 + "${SRCROOT}/Pods/Target Support Files/Pods-CNLiveDownloadManager_Tests/Pods-CNLiveDownloadManager_Tests-frameworks.sh",
  354 + "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework",
  355 + "${BUILT_PRODUCTS_DIR}/CNLiveBaseKit/CNLiveBaseKit.framework",
  356 + "${BUILT_PRODUCTS_DIR}/CNLiveBaseTools/CNLiveBaseTools.framework",
  357 + "${BUILT_PRODUCTS_DIR}/CNLiveBusinessTools/CNLiveBusinessTools.framework",
  358 + "${BUILT_PRODUCTS_DIR}/CNLiveRequestBastKit/CNLiveRequestBastKit.framework",
  359 + "${BUILT_PRODUCTS_DIR}/CNLiveTripartiteManagement/CNLiveTripartiteManagement.framework",
  360 + "${BUILT_PRODUCTS_DIR}/CNLiveUserManagement/CNLiveUserManagement.framework",
  361 + "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
  362 + "${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework",
  363 + "${BUILT_PRODUCTS_DIR}/QMUIKit/QMUIKit.framework",
  364 + );
  365 + name = "[CP] Embed Pods Frameworks";
  366 + outputFileListPaths = (
  367 + );
  368 + outputPaths = (
  369 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework",
  370 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveBaseKit.framework",
  371 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveBaseTools.framework",
  372 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveBusinessTools.framework",
  373 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveRequestBastKit.framework",
  374 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveTripartiteManagement.framework",
  375 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveUserManagement.framework",
  376 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
  377 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework",
  378 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/QMUIKit.framework",
  379 + );
  380 + runOnlyForDeploymentPostprocessing = 0;
  381 + shellPath = /bin/sh;
  382 + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CNLiveDownloadManager_Tests/Pods-CNLiveDownloadManager_Tests-frameworks.sh\"\n";
  383 + showEnvVarsInLog = 0;
  384 + };
  385 + FD4AA0BF8DE86B4A432A5A0A /* [CP] Embed Pods Frameworks */ = {
  386 + isa = PBXShellScriptBuildPhase;
  387 + buildActionMask = 2147483647;
  388 + files = (
  389 + );
  390 + inputFileListPaths = (
  391 + );
  392 + inputPaths = (
  393 + "${SRCROOT}/Pods/Target Support Files/Pods-CNLiveDownloadManager_Example/Pods-CNLiveDownloadManager_Example-frameworks.sh",
  394 + "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework",
  395 + "${BUILT_PRODUCTS_DIR}/CNLiveBaseKit/CNLiveBaseKit.framework",
  396 + "${BUILT_PRODUCTS_DIR}/CNLiveBaseTools/CNLiveBaseTools.framework",
  397 + "${BUILT_PRODUCTS_DIR}/CNLiveBusinessTools/CNLiveBusinessTools.framework",
  398 + "${BUILT_PRODUCTS_DIR}/CNLiveDownloadManager/CNLiveDownloadManager.framework",
  399 + "${BUILT_PRODUCTS_DIR}/CNLiveRequestBastKit/CNLiveRequestBastKit.framework",
  400 + "${BUILT_PRODUCTS_DIR}/CNLiveTripartiteManagement/CNLiveTripartiteManagement.framework",
  401 + "${BUILT_PRODUCTS_DIR}/CNLiveUserManagement/CNLiveUserManagement.framework",
  402 + "${BUILT_PRODUCTS_DIR}/FMDB/FMDB.framework",
  403 + "${BUILT_PRODUCTS_DIR}/MJExtension/MJExtension.framework",
  404 + "${BUILT_PRODUCTS_DIR}/QMUIKit/QMUIKit.framework",
  405 + );
  406 + name = "[CP] Embed Pods Frameworks";
  407 + outputFileListPaths = (
  408 + );
  409 + outputPaths = (
  410 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/AFNetworking.framework",
  411 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveBaseKit.framework",
  412 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveBaseTools.framework",
  413 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveBusinessTools.framework",
  414 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveDownloadManager.framework",
  415 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveRequestBastKit.framework",
  416 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveTripartiteManagement.framework",
  417 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CNLiveUserManagement.framework",
  418 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FMDB.framework",
  419 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJExtension.framework",
  420 + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/QMUIKit.framework",
  421 + );
  422 + runOnlyForDeploymentPostprocessing = 0;
  423 + shellPath = /bin/sh;
  424 + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-CNLiveDownloadManager_Example/Pods-CNLiveDownloadManager_Example-frameworks.sh\"\n";
  425 + showEnvVarsInLog = 0;
  426 + };
  427 +/* End PBXShellScriptBuildPhase section */
  428 +
  429 +/* Begin PBXSourcesBuildPhase section */
  430 + 6003F586195388D20070C39A /* Sources */ = {
  431 + isa = PBXSourcesBuildPhase;
  432 + buildActionMask = 2147483647;
  433 + files = (
  434 + 6003F59E195388D20070C39A /* CNLiveAppDelegate.m in Sources */,
  435 + 6003F5A7195388D20070C39A /* CNLiveViewController.m in Sources */,
  436 + 6003F59A195388D20070C39A /* main.m in Sources */,
  437 + );
  438 + runOnlyForDeploymentPostprocessing = 0;
  439 + };
  440 + 6003F5AA195388D20070C39A /* Sources */ = {
  441 + isa = PBXSourcesBuildPhase;
  442 + buildActionMask = 2147483647;
  443 + files = (
  444 + 6003F5BC195388D20070C39A /* Tests.m in Sources */,
  445 + );
  446 + runOnlyForDeploymentPostprocessing = 0;
  447 + };
  448 +/* End PBXSourcesBuildPhase section */
  449 +
  450 +/* Begin PBXTargetDependency section */
  451 + 6003F5B4195388D20070C39A /* PBXTargetDependency */ = {
  452 + isa = PBXTargetDependency;
  453 + target = 6003F589195388D20070C39A /* CNLiveDownloadManager_Example */;
  454 + targetProxy = 6003F5B3195388D20070C39A /* PBXContainerItemProxy */;
  455 + };
  456 +/* End PBXTargetDependency section */
  457 +
  458 +/* Begin PBXVariantGroup section */
  459 + 6003F596195388D20070C39A /* InfoPlist.strings */ = {
  460 + isa = PBXVariantGroup;
  461 + children = (
  462 + 6003F597195388D20070C39A /* en */,
  463 + );
  464 + name = InfoPlist.strings;
  465 + sourceTree = "<group>";
  466 + };
  467 + 6003F5B8195388D20070C39A /* InfoPlist.strings */ = {
  468 + isa = PBXVariantGroup;
  469 + children = (
  470 + 6003F5B9195388D20070C39A /* en */,
  471 + );
  472 + name = InfoPlist.strings;
  473 + sourceTree = "<group>";
  474 + };
  475 + 71719F9D1E33DC2100824A3D /* LaunchScreen.storyboard */ = {
  476 + isa = PBXVariantGroup;
  477 + children = (
  478 + 71719F9E1E33DC2100824A3D /* Base */,
  479 + );
  480 + name = LaunchScreen.storyboard;
  481 + sourceTree = "<group>";
  482 + };
  483 +/* End PBXVariantGroup section */
  484 +
  485 +/* Begin XCBuildConfiguration section */
  486 + 6003F5BD195388D20070C39A /* Debug */ = {
  487 + isa = XCBuildConfiguration;
  488 + buildSettings = {
  489 + ALWAYS_SEARCH_USER_PATHS = NO;
  490 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  491 + CLANG_CXX_LIBRARY = "libc++";
  492 + CLANG_ENABLE_MODULES = YES;
  493 + CLANG_ENABLE_OBJC_ARC = YES;
  494 + CLANG_WARN_BOOL_CONVERSION = YES;
  495 + CLANG_WARN_CONSTANT_CONVERSION = YES;
  496 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  497 + CLANG_WARN_EMPTY_BODY = YES;
  498 + CLANG_WARN_ENUM_CONVERSION = YES;
  499 + CLANG_WARN_INT_CONVERSION = YES;
  500 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  501 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  502 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
  503 + COPY_PHASE_STRIP = NO;
  504 + ENABLE_TESTABILITY = YES;
  505 + GCC_C_LANGUAGE_STANDARD = gnu99;
  506 + GCC_DYNAMIC_NO_PIC = NO;
  507 + GCC_OPTIMIZATION_LEVEL = 0;
  508 + GCC_PREPROCESSOR_DEFINITIONS = (
  509 + "DEBUG=1",
  510 + "$(inherited)",
  511 + );
  512 + GCC_SYMBOLS_PRIVATE_EXTERN = NO;
  513 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  514 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  515 + GCC_WARN_UNDECLARED_SELECTOR = YES;
  516 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  517 + GCC_WARN_UNUSED_FUNCTION = YES;
  518 + GCC_WARN_UNUSED_VARIABLE = YES;
  519 + IPHONEOS_DEPLOYMENT_TARGET = 9.3;
  520 + ONLY_ACTIVE_ARCH = YES;
  521 + SDKROOT = iphoneos;
  522 + TARGETED_DEVICE_FAMILY = "1,2";
  523 + };
  524 + name = Debug;
  525 + };
  526 + 6003F5BE195388D20070C39A /* Release */ = {
  527 + isa = XCBuildConfiguration;
  528 + buildSettings = {
  529 + ALWAYS_SEARCH_USER_PATHS = NO;
  530 + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
  531 + CLANG_CXX_LIBRARY = "libc++";
  532 + CLANG_ENABLE_MODULES = YES;
  533 + CLANG_ENABLE_OBJC_ARC = YES;
  534 + CLANG_WARN_BOOL_CONVERSION = YES;
  535 + CLANG_WARN_CONSTANT_CONVERSION = YES;
  536 + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
  537 + CLANG_WARN_EMPTY_BODY = YES;
  538 + CLANG_WARN_ENUM_CONVERSION = YES;
  539 + CLANG_WARN_INT_CONVERSION = YES;
  540 + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
  541 + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
  542 + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
  543 + COPY_PHASE_STRIP = YES;
  544 + ENABLE_NS_ASSERTIONS = NO;
  545 + GCC_C_LANGUAGE_STANDARD = gnu99;
  546 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
  547 + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
  548 + GCC_WARN_UNDECLARED_SELECTOR = YES;
  549 + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
  550 + GCC_WARN_UNUSED_FUNCTION = YES;
  551 + GCC_WARN_UNUSED_VARIABLE = YES;
  552 + IPHONEOS_DEPLOYMENT_TARGET = 9.3;
  553 + SDKROOT = iphoneos;
  554 + TARGETED_DEVICE_FAMILY = "1,2";
  555 + VALIDATE_PRODUCT = YES;
  556 + };
  557 + name = Release;
  558 + };
  559 + 6003F5C0195388D20070C39A /* Debug */ = {
  560 + isa = XCBuildConfiguration;
  561 + baseConfigurationReference = 56C6C35211FE6387AC196F94 /* Pods-CNLiveDownloadManager_Example.debug.xcconfig */;
  562 + buildSettings = {
  563 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  564 + DEVELOPMENT_TEAM = 94X49GG3ZW;
  565 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  566 + GCC_PREFIX_HEADER = "CNLiveDownloadManager/CNLiveDownloadManager-Prefix.pch";
  567 + INFOPLIST_FILE = "CNLiveDownloadManager/CNLiveDownloadManager-Info.plist";
  568 + IPHONEOS_DEPLOYMENT_TARGET = 9.0;
  569 + MODULE_NAME = ExampleApp;
  570 + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
  571 + PRODUCT_NAME = "$(TARGET_NAME)";
  572 + WRAPPER_EXTENSION = app;
  573 + };
  574 + name = Debug;
  575 + };
  576 + 6003F5C1195388D20070C39A /* Release */ = {
  577 + isa = XCBuildConfiguration;
  578 + baseConfigurationReference = 4E591664CF796F923B830DF3 /* Pods-CNLiveDownloadManager_Example.release.xcconfig */;
  579 + buildSettings = {
  580 + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
  581 + DEVELOPMENT_TEAM = 94X49GG3ZW;
  582 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  583 + GCC_PREFIX_HEADER = "CNLiveDownloadManager/CNLiveDownloadManager-Prefix.pch";
  584 + INFOPLIST_FILE = "CNLiveDownloadManager/CNLiveDownloadManager-Info.plist";
  585 + IPHONEOS_DEPLOYMENT_TARGET = 9.0;
  586 + MODULE_NAME = ExampleApp;
  587 + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
  588 + PRODUCT_NAME = "$(TARGET_NAME)";
  589 + WRAPPER_EXTENSION = app;
  590 + };
  591 + name = Release;
  592 + };
  593 + 6003F5C3195388D20070C39A /* Debug */ = {
  594 + isa = XCBuildConfiguration;
  595 + baseConfigurationReference = 72041DDD913A10D596ECFEEE /* Pods-CNLiveDownloadManager_Tests.debug.xcconfig */;
  596 + buildSettings = {
  597 + BUNDLE_LOADER = "$(TEST_HOST)";
  598 + FRAMEWORK_SEARCH_PATHS = (
  599 + "$(SDKROOT)/Developer/Library/Frameworks",
  600 + "$(inherited)",
  601 + "$(DEVELOPER_FRAMEWORKS_DIR)",
  602 + );
  603 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  604 + GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
  605 + GCC_PREPROCESSOR_DEFINITIONS = (
  606 + "DEBUG=1",
  607 + "$(inherited)",
  608 + );
  609 + INFOPLIST_FILE = "Tests/Tests-Info.plist";
  610 + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
  611 + PRODUCT_NAME = "$(TARGET_NAME)";
  612 + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CNLiveDownloadManager_Example.app/CNLiveDownloadManager_Example";
  613 + WRAPPER_EXTENSION = xctest;
  614 + };
  615 + name = Debug;
  616 + };
  617 + 6003F5C4195388D20070C39A /* Release */ = {
  618 + isa = XCBuildConfiguration;
  619 + baseConfigurationReference = BF5F74A07CE41BEC53E597F0 /* Pods-CNLiveDownloadManager_Tests.release.xcconfig */;
  620 + buildSettings = {
  621 + BUNDLE_LOADER = "$(TEST_HOST)";
  622 + FRAMEWORK_SEARCH_PATHS = (
  623 + "$(SDKROOT)/Developer/Library/Frameworks",
  624 + "$(inherited)",
  625 + "$(DEVELOPER_FRAMEWORKS_DIR)",
  626 + );
  627 + GCC_PRECOMPILE_PREFIX_HEADER = YES;
  628 + GCC_PREFIX_HEADER = "Tests/Tests-Prefix.pch";
  629 + INFOPLIST_FILE = "Tests/Tests-Info.plist";
  630 + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.${PRODUCT_NAME:rfc1034identifier}";
  631 + PRODUCT_NAME = "$(TARGET_NAME)";
  632 + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CNLiveDownloadManager_Example.app/CNLiveDownloadManager_Example";
  633 + WRAPPER_EXTENSION = xctest;
  634 + };
  635 + name = Release;
  636 + };
  637 +/* End XCBuildConfiguration section */
  638 +
  639 +/* Begin XCConfigurationList section */
  640 + 6003F585195388D10070C39A /* Build configuration list for PBXProject "CNLiveDownloadManager" */ = {
  641 + isa = XCConfigurationList;
  642 + buildConfigurations = (
  643 + 6003F5BD195388D20070C39A /* Debug */,
  644 + 6003F5BE195388D20070C39A /* Release */,
  645 + );
  646 + defaultConfigurationIsVisible = 0;
  647 + defaultConfigurationName = Release;
  648 + };
  649 + 6003F5BF195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLiveDownloadManager_Example" */ = {
  650 + isa = XCConfigurationList;
  651 + buildConfigurations = (
  652 + 6003F5C0195388D20070C39A /* Debug */,
  653 + 6003F5C1195388D20070C39A /* Release */,
  654 + );
  655 + defaultConfigurationIsVisible = 0;
  656 + defaultConfigurationName = Release;
  657 + };
  658 + 6003F5C2195388D20070C39A /* Build configuration list for PBXNativeTarget "CNLiveDownloadManager_Tests" */ = {
  659 + isa = XCConfigurationList;
  660 + buildConfigurations = (
  661 + 6003F5C3195388D20070C39A /* Debug */,
  662 + 6003F5C4195388D20070C39A /* Release */,
  663 + );
  664 + defaultConfigurationIsVisible = 0;
  665 + defaultConfigurationName = Release;
  666 + };
  667 +/* End XCConfigurationList section */
  668 + };
  669 + rootObject = 6003F582195388D10070C39A /* Project object */;
  670 +}
... ...
Example/CNLiveDownloadManager.xcodeproj/xcshareddata/xcschemes/CNLiveDownloadManager-Example.xcscheme 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<Scheme
  3 + LastUpgradeVersion = "0720"
  4 + version = "1.3">
  5 + <BuildAction
  6 + parallelizeBuildables = "YES"
  7 + buildImplicitDependencies = "YES">
  8 + <BuildActionEntries>
  9 + <BuildActionEntry
  10 + buildForTesting = "YES"
  11 + buildForRunning = "YES"
  12 + buildForProfiling = "YES"
  13 + buildForArchiving = "YES"
  14 + buildForAnalyzing = "YES">
  15 + <BuildableReference
  16 + BuildableIdentifier = "primary"
  17 + BlueprintIdentifier = "6003F589195388D20070C39A"
  18 + BuildableName = "CNLiveDownloadManager_Example.app"
  19 + BlueprintName = "CNLiveDownloadManager_Example"
  20 + ReferencedContainer = "container:CNLiveDownloadManager.xcodeproj">
  21 + </BuildableReference>
  22 + </BuildActionEntry>
  23 + </BuildActionEntries>
  24 + </BuildAction>
  25 + <TestAction
  26 + buildConfiguration = "Debug"
  27 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  28 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  29 + shouldUseLaunchSchemeArgsEnv = "YES">
  30 + <Testables>
  31 + <TestableReference
  32 + skipped = "NO">
  33 + <BuildableReference
  34 + BuildableIdentifier = "primary"
  35 + BlueprintIdentifier = "6003F5AD195388D20070C39A"
  36 + BuildableName = "CNLiveDownloadManager_Tests.xctest"
  37 + BlueprintName = "CNLiveDownloadManager_Tests"
  38 + ReferencedContainer = "container:CNLiveDownloadManager.xcodeproj">
  39 + </BuildableReference>
  40 + </TestableReference>
  41 + </Testables>
  42 + <MacroExpansion>
  43 + <BuildableReference
  44 + BuildableIdentifier = "primary"
  45 + BlueprintIdentifier = "6003F589195388D20070C39A"
  46 + BuildableName = "CNLiveDownloadManager_Example.app"
  47 + BlueprintName = "CNLiveDownloadManager_Example"
  48 + ReferencedContainer = "container:CNLiveDownloadManager.xcodeproj">
  49 + </BuildableReference>
  50 + </MacroExpansion>
  51 + <AdditionalOptions>
  52 + </AdditionalOptions>
  53 + </TestAction>
  54 + <LaunchAction
  55 + buildConfiguration = "Debug"
  56 + selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
  57 + selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
  58 + launchStyle = "0"
  59 + useCustomWorkingDirectory = "NO"
  60 + ignoresPersistentStateOnLaunch = "NO"
  61 + debugDocumentVersioning = "YES"
  62 + debugServiceExtension = "internal"
  63 + allowLocationSimulation = "YES">
  64 + <BuildableProductRunnable
  65 + runnableDebuggingMode = "0">
  66 + <BuildableReference
  67 + BuildableIdentifier = "primary"
  68 + BlueprintIdentifier = "6003F589195388D20070C39A"
  69 + BuildableName = "CNLiveDownloadManager_Example.app"
  70 + BlueprintName = "CNLiveDownloadManager_Example"
  71 + ReferencedContainer = "container:CNLiveDownloadManager.xcodeproj">
  72 + </BuildableReference>
  73 + </BuildableProductRunnable>
  74 + <AdditionalOptions>
  75 + </AdditionalOptions>
  76 + </LaunchAction>
  77 + <ProfileAction
  78 + buildConfiguration = "Release"
  79 + shouldUseLaunchSchemeArgsEnv = "YES"
  80 + savedToolIdentifier = ""
  81 + useCustomWorkingDirectory = "NO"
  82 + debugDocumentVersioning = "YES">
  83 + <BuildableProductRunnable
  84 + runnableDebuggingMode = "0">
  85 + <BuildableReference
  86 + BuildableIdentifier = "primary"
  87 + BlueprintIdentifier = "6003F589195388D20070C39A"
  88 + BuildableName = "CNLiveDownloadManager_Example.app"
  89 + BlueprintName = "CNLiveDownloadManager_Example"
  90 + ReferencedContainer = "container:CNLiveDownloadManager.xcodeproj">
  91 + </BuildableReference>
  92 + </BuildableProductRunnable>
  93 + </ProfileAction>
  94 + <AnalyzeAction
  95 + buildConfiguration = "Debug">
  96 + </AnalyzeAction>
  97 + <ArchiveAction
  98 + buildConfiguration = "Release"
  99 + revealArchiveInOrganizer = "YES">
  100 + </ArchiveAction>
  101 +</Scheme>
... ...
Example/CNLiveDownloadManager/Base.lproj/LaunchScreen.storyboard 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
  3 + <device id="retina4_7" orientation="portrait">
  4 + <adaptation id="fullscreen"/>
  5 + </device>
  6 + <dependencies>
  7 + <deployment identifier="iOS"/>
  8 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
  9 + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
  10 + </dependencies>
  11 + <scenes>
  12 + <!--View Controller-->
  13 + <scene sceneID="EHf-IW-A2E">
  14 + <objects>
  15 + <viewController id="01J-lp-oVM" sceneMemberID="viewController">
  16 + <layoutGuides>
  17 + <viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
  18 + <viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
  19 + </layoutGuides>
  20 + <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
  21 + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
  22 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  23 + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
  24 + </view>
  25 + </viewController>
  26 + <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
  27 + </objects>
  28 + <point key="canvasLocation" x="53" y="375"/>
  29 + </scene>
  30 + </scenes>
  31 +</document>
... ...
Example/CNLiveDownloadManager/Base.lproj/Main.storyboard 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="whP-gf-Uak">
  3 + <device id="retina4_7" orientation="portrait">
  4 + <adaptation id="fullscreen"/>
  5 + </device>
  6 + <dependencies>
  7 + <deployment identifier="iOS"/>
  8 + <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
  9 + <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
  10 + </dependencies>
  11 + <scenes>
  12 + <!--View Controller-->
  13 + <scene sceneID="wQg-tq-qST">
  14 + <objects>
  15 + <viewController id="whP-gf-Uak" customClass="CNLiveViewController" sceneMemberID="viewController">
  16 + <layoutGuides>
  17 + <viewControllerLayoutGuide type="top" id="uEw-UM-LJ8"/>
  18 + <viewControllerLayoutGuide type="bottom" id="Mvr-aV-6Um"/>
  19 + </layoutGuides>
  20 + <view key="view" contentMode="scaleToFill" id="TpU-gO-2f1">
  21 + <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
  22 + <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
  23 + <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
  24 + </view>
  25 + </viewController>
  26 + <placeholder placeholderIdentifier="IBFirstResponder" id="tc2-Qw-aMS" userLabel="First Responder" sceneMemberID="firstResponder"/>
  27 + </objects>
  28 + <point key="canvasLocation" x="305" y="433"/>
  29 + </scene>
  30 + </scenes>
  31 +</document>
... ...
Example/CNLiveDownloadManager/CNLiveAppDelegate.h 0 → 100644
  1 +//
  2 +// CNLiveAppDelegate.h
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 05/31/2019.
  6 +// Copyright (c) 2019 殷巧娟. All rights reserved.
  7 +//
  8 +
  9 +@import UIKit;
  10 +
  11 +@interface CNLiveAppDelegate : UIResponder <UIApplicationDelegate>
  12 +
  13 +@property (strong, nonatomic) UIWindow *window;
  14 +
  15 +@end
... ...
Example/CNLiveDownloadManager/CNLiveAppDelegate.m 0 → 100644
  1 +//
  2 +// CNLiveAppDelegate.m
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 05/31/2019.
  6 +// Copyright (c) 2019 殷巧娟. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveAppDelegate.h"
  10 +
  11 +@implementation CNLiveAppDelegate
  12 +
  13 +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  14 +{
  15 + // Override point for customization after application launch.
  16 + return YES;
  17 +}
  18 +
  19 +- (void)applicationWillResignActive:(UIApplication *)application
  20 +{
  21 + // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
  22 + // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
  23 +}
  24 +
  25 +- (void)applicationDidEnterBackground:(UIApplication *)application
  26 +{
  27 + // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
  28 + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
  29 +}
  30 +
  31 +- (void)applicationWillEnterForeground:(UIApplication *)application
  32 +{
  33 + // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
  34 +}
  35 +
  36 +- (void)applicationDidBecomeActive:(UIApplication *)application
  37 +{
  38 + // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
  39 +}
  40 +
  41 +- (void)applicationWillTerminate:(UIApplication *)application
  42 +{
  43 + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
  44 +}
  45 +
  46 +@end
... ...
Example/CNLiveDownloadManager/CNLiveDownloadManager-Info.plist 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CFBundleDevelopmentRegion</key>
  6 + <string>en</string>
  7 + <key>CFBundleDisplayName</key>
  8 + <string>${PRODUCT_NAME}</string>
  9 + <key>CFBundleExecutable</key>
  10 + <string>${EXECUTABLE_NAME}</string>
  11 + <key>CFBundleIdentifier</key>
  12 + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  13 + <key>CFBundleInfoDictionaryVersion</key>
  14 + <string>6.0</string>
  15 + <key>CFBundleName</key>
  16 + <string>${PRODUCT_NAME}</string>
  17 + <key>CFBundlePackageType</key>
  18 + <string>APPL</string>
  19 + <key>CFBundleShortVersionString</key>
  20 + <string>1.0</string>
  21 + <key>CFBundleSignature</key>
  22 + <string>????</string>
  23 + <key>CFBundleVersion</key>
  24 + <string>1.0</string>
  25 + <key>LSRequiresIPhoneOS</key>
  26 + <true/>
  27 + <key>UILaunchStoryboardName</key>
  28 + <string>LaunchScreen</string>
  29 + <key>UIMainStoryboardFile</key>
  30 + <string>Main</string>
  31 + <key>UIRequiredDeviceCapabilities</key>
  32 + <array>
  33 + <string>armv7</string>
  34 + </array>
  35 + <key>UISupportedInterfaceOrientations</key>
  36 + <array>
  37 + <string>UIInterfaceOrientationPortrait</string>
  38 + <string>UIInterfaceOrientationLandscapeLeft</string>
  39 + <string>UIInterfaceOrientationLandscapeRight</string>
  40 + </array>
  41 + <key>UISupportedInterfaceOrientations~ipad</key>
  42 + <array>
  43 + <string>UIInterfaceOrientationPortrait</string>
  44 + <string>UIInterfaceOrientationPortraitUpsideDown</string>
  45 + <string>UIInterfaceOrientationLandscapeLeft</string>
  46 + <string>UIInterfaceOrientationLandscapeRight</string>
  47 + </array>
  48 +</dict>
  49 +</plist>
... ...
Example/CNLiveDownloadManager/CNLiveDownloadManager-Prefix.pch 0 → 100644
  1 +//
  2 +// Prefix header
  3 +//
  4 +// The contents of this file are implicitly included at the beginning of every source file.
  5 +//
  6 +
  7 +#import <Availability.h>
  8 +
  9 +#ifndef __IPHONE_5_0
  10 +#warning "This project uses features only available in iOS SDK 5.0 and later."
  11 +#endif
  12 +
  13 +#ifdef __OBJC__
  14 + @import UIKit;
  15 + @import Foundation;
  16 +#endif
... ...
Example/CNLiveDownloadManager/CNLiveViewController.h 0 → 100644
  1 +//
  2 +// CNLiveViewController.h
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 05/31/2019.
  6 +// Copyright (c) 2019 殷巧娟. All rights reserved.
  7 +//
  8 +
  9 +@import UIKit;
  10 +
  11 +@interface CNLiveViewController : UIViewController
  12 +
  13 +@end
... ...
Example/CNLiveDownloadManager/CNLiveViewController.m 0 → 100644
  1 +//
  2 +// CNLiveViewController.m
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 05/31/2019.
  6 +// Copyright (c) 2019 殷巧娟. All rights reserved.
  7 +//
  8 +
  9 +#import "CNLiveViewController.h"
  10 +@interface CNLiveViewController ()
  11 +
  12 +@end
  13 +
  14 +@implementation CNLiveViewController
  15 +
  16 +- (void)viewDidLoad
  17 +{
  18 + [super viewDidLoad];
  19 + // Do any additional setup after loading the view, typically from a nib.
  20 +}
  21 +
  22 +- (void)didReceiveMemoryWarning
  23 +{
  24 + [super didReceiveMemoryWarning];
  25 + // Dispose of any resources that can be recreated.
  26 +}
  27 +
  28 +@end
... ...
Example/CNLiveDownloadManager/Images.xcassets/AppIcon.appiconset/Contents.json 0 → 100644
  1 +{
  2 + "images" : [
  3 + {
  4 + "idiom" : "iphone",
  5 + "size" : "20x20",
  6 + "scale" : "2x"
  7 + },
  8 + {
  9 + "idiom" : "iphone",
  10 + "size" : "20x20",
  11 + "scale" : "3x"
  12 + },
  13 + {
  14 + "idiom" : "iphone",
  15 + "size" : "29x29",
  16 + "scale" : "2x"
  17 + },
  18 + {
  19 + "idiom" : "iphone",
  20 + "size" : "29x29",
  21 + "scale" : "3x"
  22 + },
  23 + {
  24 + "idiom" : "iphone",
  25 + "size" : "40x40",
  26 + "scale" : "2x"
  27 + },
  28 + {
  29 + "idiom" : "iphone",
  30 + "size" : "40x40",
  31 + "scale" : "3x"
  32 + },
  33 + {
  34 + "idiom" : "iphone",
  35 + "size" : "60x60",
  36 + "scale" : "2x"
  37 + },
  38 + {
  39 + "idiom" : "iphone",
  40 + "size" : "60x60",
  41 + "scale" : "3x"
  42 + },
  43 + {
  44 + "idiom" : "ipad",
  45 + "size" : "20x20",
  46 + "scale" : "1x"
  47 + },
  48 + {
  49 + "idiom" : "ipad",
  50 + "size" : "20x20",
  51 + "scale" : "2x"
  52 + },
  53 + {
  54 + "idiom" : "ipad",
  55 + "size" : "29x29",
  56 + "scale" : "1x"
  57 + },
  58 + {
  59 + "idiom" : "ipad",
  60 + "size" : "29x29",
  61 + "scale" : "2x"
  62 + },
  63 + {
  64 + "idiom" : "ipad",
  65 + "size" : "40x40",
  66 + "scale" : "1x"
  67 + },
  68 + {
  69 + "idiom" : "ipad",
  70 + "size" : "40x40",
  71 + "scale" : "2x"
  72 + },
  73 + {
  74 + "idiom" : "ipad",
  75 + "size" : "76x76",
  76 + "scale" : "1x"
  77 + },
  78 + {
  79 + "idiom" : "ipad",
  80 + "size" : "76x76",
  81 + "scale" : "2x"
  82 + },
  83 + {
  84 + "idiom" : "ipad",
  85 + "size" : "83.5x83.5",
  86 + "scale" : "2x"
  87 + },
  88 + {
  89 + "idiom" : "ios-marketing",
  90 + "size" : "1024x1024",
  91 + "scale" : "1x"
  92 + }
  93 + ],
  94 + "info" : {
  95 + "version" : 1,
  96 + "author" : "xcode"
  97 + }
  98 +}
... ...
Example/CNLiveDownloadManager/en.lproj/InfoPlist.strings 0 → 100644
  1 +/* Localized versions of Info.plist keys */
  2 +
... ...
Example/CNLiveDownloadManager/main.m 0 → 100644
  1 +//
  2 +// main.m
  3 +// CNLiveDownloadManager
  4 +//
  5 +// Created by 殷巧娟 on 05/31/2019.
  6 +// Copyright (c) 2019 殷巧娟. All rights reserved.
  7 +//
  8 +
  9 +@import UIKit;
  10 +#import "CNLiveAppDelegate.h"
  11 +
  12 +int main(int argc, char * argv[])
  13 +{
  14 + @autoreleasepool {
  15 + return UIApplicationMain(argc, argv, nil, NSStringFromClass([CNLiveAppDelegate class]));
  16 + }
  17 +}
... ...
Example/Podfile 0 → 100644
  1 +use_frameworks!
  2 +
  3 +platform :ios, '9.0'
  4 +source 'https://github.com/CocoaPods/Specs.git'
  5 +source 'http://bj.gitlab.cnlive.com/ios-team/CNLiveRepos.git'
  6 +
  7 +target 'CNLiveDownloadManager_Example' do
  8 + pod 'CNLiveDownloadManager', :path => '../'
  9 + pod 'CNLiveTripartiteManagement/FMDB'
  10 + pod 'CNLiveBaseKit'
  11 + pod 'CNLiveTripartiteManagement/MJExtension'
  12 + pod 'CNLiveBaseTools'
  13 + pod 'CNLiveEnvironmentConfiguration'
  14 + pod 'CNLiveBusinessTools'
  15 + pod 'CNLiveBaseKit'
  16 + pod 'CNLiveRequestBastKit'
  17 + pod 'CNLiveTripartiteManagement/QMUIKit'
  18 + target 'CNLiveDownloadManager_Tests' do
  19 + inherit! :search_paths
  20 +
  21 + pod 'CNLiveTripartiteManagement/FMDB'
  22 + pod 'CNLiveBaseKit'
  23 + pod 'CNLiveTripartiteManagement/MJExtension'
  24 + pod 'CNLiveEnvironmentConfiguration'
  25 + pod 'CNLiveBusinessTools'
  26 + pod 'CNLiveBaseKit'
  27 + pod 'CNLiveRequestBastKit'
  28 + pod 'CNLiveTripartiteManagement/QMUIKit'
  29 + pod 'CNLiveBaseTools'
  30 + end
  31 +end
... ...
Example/Tests/Tests-Info.plist 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
  3 +<plist version="1.0">
  4 +<dict>
  5 + <key>CFBundleDevelopmentRegion</key>
  6 + <string>en</string>
  7 + <key>CFBundleExecutable</key>
  8 + <string>${EXECUTABLE_NAME}</string>
  9 + <key>CFBundleIdentifier</key>
  10 + <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
  11 + <key>CFBundleInfoDictionaryVersion</key>
  12 + <string>6.0</string>
  13 + <key>CFBundlePackageType</key>
  14 + <string>BNDL</string>
  15 + <key>CFBundleShortVersionString</key>
  16 + <string>1.0</string>
  17 + <key>CFBundleSignature</key>
  18 + <string>????</string>
  19 + <key>CFBundleVersion</key>
  20 + <string>1</string>
  21 +</dict>
  22 +</plist>
... ...
Example/Tests/Tests-Prefix.pch 0 → 100644
  1 +// The contents of this file are implicitly included at the beginning of every test case source file.
  2 +
  3 +#ifdef __OBJC__
  4 +
  5 +
  6 +
  7 +#endif
... ...
Example/Tests/Tests.m 0 → 100644
  1 +//
  2 +// CNLiveDownloadManagerTests.m
  3 +// CNLiveDownloadManagerTests
  4 +//
  5 +// Created by 殷巧娟 on 05/31/2019.
  6 +// Copyright (c) 2019 殷巧娟. All rights reserved.
  7 +//
  8 +
  9 +@import XCTest;
  10 +
  11 +@interface Tests : XCTestCase
  12 +
  13 +@end
  14 +
  15 +@implementation Tests
  16 +
  17 +- (void)setUp
  18 +{
  19 + [super setUp];
  20 + // Put setup code here. This method is called before the invocation of each test method in the class.
  21 +}
  22 +
  23 +- (void)tearDown
  24 +{
  25 + // Put teardown code here. This method is called after the invocation of each test method in the class.
  26 + [super tearDown];
  27 +}
  28 +
  29 +- (void)testExample
  30 +{
  31 + XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
  32 +}
  33 +
  34 +@end
  35 +
... ...
Example/Tests/en.lproj/InfoPlist.strings 0 → 100644
  1 +/* Localized versions of Info.plist keys */
  2 +
... ...
LICENSE 0 → 100644
  1 +Copyright (c) 2019 殷巧娟 <1427945373@qq.com>
  2 +
  3 +Permission is hereby granted, free of charge, to any person obtaining a copy
  4 +of this software and associated documentation files (the "Software"), to deal
  5 +in the Software without restriction, including without limitation the rights
  6 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7 +copies of the Software, and to permit persons to whom the Software is
  8 +furnished to do so, subject to the following conditions:
  9 +
  10 +The above copyright notice and this permission notice shall be included in
  11 +all copies or substantial portions of the Software.
  12 +
  13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19 +THE SOFTWARE.
... ...
README.md
  1 +# CNLiveDownloadManager
  2 +
  3 +[![CI Status](https://img.shields.io/travis/殷巧娟/CNLiveDownloadManager.svg?style=flat)](https://travis-ci.org/殷巧娟/CNLiveDownloadManager)
  4 +[![Version](https://img.shields.io/cocoapods/v/CNLiveDownloadManager.svg?style=flat)](https://cocoapods.org/pods/CNLiveDownloadManager)
  5 +[![License](https://img.shields.io/cocoapods/l/CNLiveDownloadManager.svg?style=flat)](https://cocoapods.org/pods/CNLiveDownloadManager)
  6 +[![Platform](https://img.shields.io/cocoapods/p/CNLiveDownloadManager.svg?style=flat)](https://cocoapods.org/pods/CNLiveDownloadManager)
  7 +
  8 +## Example
  9 +
  10 +To run the example project, clone the repo, and run `pod install` from the Example directory first.
  11 +
  12 +## Requirements
  13 +
  14 +## Installation
  15 +
  16 +CNLiveDownloadManager is available through [CocoaPods](https://cocoapods.org). To install
  17 +it, simply add the following line to your Podfile:
  18 +
  19 +```ruby
  20 +pod 'CNLiveDownloadManager'
  21 +```
  22 +
  23 +## Author
  24 +
  25 +殷巧娟, 1427945373@qq.com
  26 +
  27 +## License
  28 +
  29 +CNLiveDownloadManager is available under the MIT license. See the LICENSE file for more info.
... ...
_Pods.xcodeproj 0 → 120000
  1 +Example/Pods/Pods.xcodeproj
0 2 \ No newline at end of file
... ...