- Using NSURLSessionDownloadTask, required iOS 7 and up.
- Using another operation queue for downloading.
- Controlling concurrent tasks for parallel downloading, can be tuned to quality of the internet connection.
- Possibility to inform about queue state via delegate, blocks and notifications. Can be selected which method to use.
- Progress calculating on downloaded data size per each task, not on simple count of tasks, for smoothly progressing.
- Queue can be serialized/deserialized for future reusing.
- Required ARC.
platform :ios, '7.0'
pod 'REDownloadTasksQueue'
import REDownloadTasksQueue
...
let queue = REDownloadTasksQueue()
queue.continueOnTaskError = true // Should queue continue on any task error.
for ... {
let fromURLString = ...
let storePath = ...
queue.addURLString(fromURLString, withStorePath: storePath) // add as URL string
// or
queue.addURL(NSURL(string: fromURLString), withStorePath: storePath) // add as URL
// or
queue.addURLRequest(NSURLRequest(), withStorePath: storePath) // add as setuped request
}
queue.start() // start queue
#import <REDownloadTasksQueue/REDownloadTasksQueue.h> // include single queue header file
self.queue = [[REDownloadTasksQueue alloc] init]; // create and store strongly queue object
_queue.continueOnTaskError = YES; // Should queue continue on any task error.
for (...) { // iterate URL's
NSString * fromURLString = ...; // URL string for download file
NSString * storePath = ...; // Full path for storing downloaded file data
[_queue addURLString:fromURLString withStorePath:storePath]; // add as URL string
// or
[_queue addURL:[NSURL URLWithString:fromURLString] withStorePath:storePath]; // add as URL
// or
[_queue addURLRequest:[[NSURLRequest alloc] init] withStorePath:storePath]; // add as setuped request
}
[_queue start]; // start queue
queue.onErrorOccurredHandler = { queue, error, downloadURL, storeFilePathURL in
print("onErrorOccurred, error: \(error), from: \(downloadURL), to: \(storeFilePathURL)")
}
queue.onFinishedHandler = { queue in
print("onFinished")
}
queue.onProgressHandler = { queue, progress in
print("onProgress, progress: \(progress)")
}
[_queue setOnErrorOccurredHandler:^(REDownloadTasksQueue * queue, NSError * error, NSURL * downloadURL, NSURL * storeFilePathURL) {
NSLog(@"onErrorOccurred, error: %@, from: %@, to: %@", error, downloadURL, storeFilePathURL);
}];
[_queue setOnFinishedHandler:^(REDownloadTasksQueue * queue) {
NSLog(@"onFinished");
}];
[_queue setOnProgressHandler:^(REDownloadTasksQueue * queue, float progress) {
NSLog(@"onProgress, progress: %f %%", progress);
}];
#pragma mark - REDownloadTasksQueue notifications
- (void) onOnDownloadTasksQueueErrorOccurredNotification:(NSNotification *) notification {
NSDictionary * userInfo = [notification userInfo];
REDownloadTasksQueue * queue = [userInfo objectForKey:kREDownloadTasksQueueQueueKey];
id userObject = [userInfo objectForKey:kREDownloadTasksQueueUserObjectKey];
NSError * error = [userInfo objectForKey:kREDownloadTasksQueueErrorKey];
NSURL * downloadURL = [userInfo objectForKey:kREDownloadTasksQueueDownloadURLKey];
NSURL * storeURL = [userInfo objectForKey:kREDownloadTasksQueueStoreURLKey];
// Process error
}
- (void) onOnDownloadTasksQueueFinishedNotification:(NSNotification *) notification {
NSDictionary * userInfo = [notification userInfo];
REDownloadTasksQueue * queue = [userInfo objectForKey:kREDownloadTasksQueueQueueKey];
id userObject = [userInfo objectForKey:kREDownloadTasksQueueUserObjectKey];
// Process finished situation
}
- (void) onOnDownloadTasksQueueProgressChangedNotification:(NSNotification *) notification {
NSDictionary * userInfo = [notification userInfo];
REDownloadTasksQueue * queue = [userInfo objectForKey:kREDownloadTasksQueueQueueKey];
id userObject = [userInfo objectForKey:kREDownloadTasksQueueUserObjectKey];
NSNumber * progressNumber = [userInfo objectForKey:kREDownloadTasksQueueProgressKey];
NSLog(@"onProgress, progress: %f %%", [progressNumber floatValue]);
// Process progressing
}
// setup queue observing
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onOnDownloadTasksQueueErrorOccurredNotification:)
name:kREDownloadTasksQueueErrorNotification
object:nil /* or queue object */];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onOnDownloadTasksQueueFinishedNotification:)
name:kREDownloadTasksQueueDidFinishedNotification
object:nil /* or queue object */];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onOnDownloadTasksQueueProgressChangedNotification:)
name:kREDownloadTasksQueueProgressChangedNotification
object:nil /* or queue object */];
//MARK: REDownloadTasksQueueDelegate
func onREDownloadTasksQueueFinished(queue: REDownloadTasksQueue) {
// Process finished
}
func onREDownloadTasksQueue(queue: REDownloadTasksQueue, progress: Float) {
print("onProgress, progress: \(progress)")
// Process progressing
}
func onREDownloadTasksQueue(queue: REDownloadTasksQueue, error: NSError?, downloadURL: NSURL?, storeURL: NSURL?) {
// Process error
}
// setup queue delegate
queue.delegate = self
#pragma mark - REDownloadTasksQueueDelegate
- (void) onREDownloadTasksQueueFinished:(REDownloadTasksQueue *) queue {
// Process finished
}
- (void) onREDownloadTasksQueue:(REDownloadTasksQueue *) queue
progress:(float) progress {
NSLog(@"onProgress, progress: %f %%", progress);
// Process progressing
}
- (void) onREDownloadTasksQueue:(REDownloadTasksQueue *) queue
error:(NSError *) error
downloadURL:(NSURL *) downloadURL
storeURL:(NSURL *) storeURL {
// Process error
}
// setup queue delegate
[_queue setDelegate:self];
__weak SomeClassWhichHoldsQueue * weakSelf = self;
[_queue cancelAndSerializeWithRestorationID:^(NSString * restorationID){
NSLog(@"Stored restorationID: %@", restorationID);
weakSelf.restorationID = restorationID;
}];
__weak SomeClassWhichHoldsQueue * weakSelf = self;
[REDownloadTasksQueue createWithRestorationID:weakSelf.restorationID
andCompletionHandler:^(REDownloadTasksQueue * restoredQueue, NSError * error) {
NSLog(@"Restored");
weakSelf.queue = restoredQueue;
[restoredQueue start];
}];
The MIT License (MIT)
Copyright (c) 2014 - 2016 Kulykov Oleh info@resident.name
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.