通过一个单例持有多个下载NSURLSessionDownloadTask

这篇博客探讨了如何在iOS开发中通过一个单例实例来管理并创建多个NSURLSessionDownloadTask。通过在单例中添加一个私有字典属性,可以存储并跟踪不同的下载任务,从而实现多个下载任务的同时进行。提供的代码示例展示了如何实现这个功能,便于在实际应用中复用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们通常使用单例来创建我们的下载,以便在各个类中使用,但是单例只能是唯一的,那么如何通过一个单例创建多个下载?我们可以在单例中添加一个私有的可变字典属性,将多个下载存入字典,如此,我们通过一个单例来创建多个下载任务,下面的代码,定义了有效的接口,可以很方便的在其它app中使用:

创建一个NSURLSessionDownloadTask类

//
//  Download.h
//  TestOfDownload

#import <Foundation/Foundation.h>
//定义block
typedef void(^finishedPath)(NSString *path, NSString *url);
typedef void(^downloading)(long long writeData, float progress);

//定义一个代理
@protocol DownloadDelegate <NSObject>
//一个一定要执行的代理, 作用: 让单例代理对象销毁下载对象
- (void)moveFinishedPathWithURL:(NSString *)url;
@end


@interface Download : NSObject<NSURLSessionDownloadDelegate>
@property (strong, nonatomic, readonly) NSString *url;//下载网址
@property (strong, nonatomic) NSURLSession *session; // 下载的支持父类
@property (strong, nonatomic) NSURLSessionDownloadTask *downloadTask;//下载;
@property (strong, nonatomic) NSMutableData *data; //保存断点下载的数据
@property (assign, nonatomic) id<DownloadDelegate>delegate;


//创建一个下载
- (instancetype)initWithURL:(NSString *)url;
//暂停接口
- (void)didSuspend;
//恢复下载接口
- (void)didResume;
//下载进度接口
- (void)didDownloading:(downloading)downloading finish:(finishedPath)finished;
@end

//
//  Download.m
//  TestOfDownload
#import "Download.h"

@interface Download ()
@property (copy, nonatomic) finishedPath downloadPath;//下载完成后路径
@property (copy, nonatomic) downloading downloading;//下载中数据
@end

@implementation Download

- (void)dealloc
{
    _delegate = nil;
}
- (instancetype)initWithURL:(NSString *)url {
    self = [super init];
    if (self) {
        _url = url; //赋值,readonly ,使用下划线
        self.session = [NSURLSession sessionWithConfiguration:nil delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        self.downloadTask = [self.session downloadTaskWithURL:[NSURL URLWithString:url]];
        [self.downloadTask resume];//调用父类NSURLSessionTask的重新下载方法
    }
    return self;
}
//暂停接口
- (void)didSuspend {
    __weak typeof(self) vc = self;
    [self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
        vc.data = (NSMutableData *)resumeData;
        vc.downloadTask = nil;
    }];
}
//恢复下载接口
- (void)didResume {
    self.downloadTask = [self.session downloadTaskWithResumeData:self.data];
    [self.downloadTask resume]; //调用父类的重新下载方法
    self.data = nil;
}
//下载进度接口
- (void)didDownloading:(downloading)downloading finish:(finishedPath)finished {
    self.downloading = downloading; //block赋值
    self.downloadPath = finished;
}


#pragma mark-----实现NSURLSessionDownloadDelegate代理------
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location {
    //完成下载
    
    //下载完成后移动到的文件夹路径
    NSString *cache = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    //下载完成后移动的文件路径
    NSString *file = [cache stringByAppendingPathComponent:downloadTask.response.suggestedFilename];//服务器的名字
    //对文件进行操作
    NSFileManager *fm = [NSFileManager defaultManager];
    //移动文件
    [fm moveItemAtPath:location.path toPath:file error:nil];
    
    //通过bloack,将下载网址和文件路径传出去
    self.downloadPath(file,self.url);
    //下载完成后执行销毁代理
    if ([_delegate respondsToSelector:@selector(moveFinishedPathWithURL:)]) {
        [_delegate moveFinishedPathWithURL:self.url];
    }
    
    //销毁对象,同NSTimer
    [self.session invalidateAndCancel];
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
      didWriteData:(int64_t)bytesWritten
 totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    //下载中
    
    //block传递下载的数据和进度
    float progress = (float)totalBytesWritten / totalBytesExpectedToWrite;
    self.downloading(bytesWritten, progress * 100.0);
    
}
@end

创建一个单例类:

//
//  SingletonDownload.h
//  TestOfDownload

#import <Foundation/Foundation.h>
#import "Download.h"
@interface SingletonDownload : NSObject<DownloadDelegate>

//创建单例
+ (instancetype)shareSingletonDownloader;
//添加一个下载
- (Download *)addDownloaderWithURL:(NSString *)url;
//根据url找到下载
- (Download *)findDownloaderWithURL:(NSString *)url;
//返回所有下载
- (NSArray *)allDownloader;

@end

//
//  SingletonDownload.m
//  TestOfDownload

#import "SingletonDownload.h"

@interface SingletonDownload ()
@property (strong, nonatomic) NSMutableDictionary *allDownloaderDic;//创建一个字典,用来保存当前的下载,使单例持有它,从而不会被销毁
@end

@implementation SingletonDownload
- (NSMutableDictionary *)allDownloaderDic {
    if (!_allDownloaderDic) {
        self.allDownloaderDic = [NSMutableDictionary dictionary];
    }
    return _allDownloaderDic;
}

//创建单例
+ (instancetype)shareSingletonDownloader {
    static SingletonDownload *singleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleton = [[SingletonDownload alloc] init];
    });
    return singleton;
}
//添加一个下载
- (Download *)addDownloaderWithURL:(NSString *)url {
    //判断是否有下载
    Download *downloader =self.allDownloaderDic[url];
    downloader.delegate = self;
    if (!downloader) {
       downloader = [[Download alloc] initWithURL:url];
        //将单例存入字典中
        [self.allDownloaderDic setValue:downloader forKey:url];
    }
    return downloader;
}
//根据url找到下载
- (Download *)findDownloaderWithURL:(NSString *)url {
    return self.allDownloaderDic[url];
}
//返回所有下载
- (NSArray *)allDownloader {
    return [self.allDownloaderDic allValues];
}

#pragma mark-----代理执行----
- (void)moveFinishedPathWithURL:(NSString *)url {
    //下载完成,销毁对象
    [self.allDownloaderDic removeObjectForKey:url];
}

@end



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值