Voici un composant qui permet de télécharger des fichiers de manières asynchrone. L'avantage de cette méthode est, hormis une gestion plus précise des événements de téléchargement, de libérer du temps/machine pour faire autre chose pendant la session de téléchargement. Typiquement, l'ajout d'un progressView à ce composant est assez facile.
VSDownloadManager utilise NSURLConnection en mode asynchrone (et non NSURLDownload qui n'est pas implémenté sur l'iPhone).
Téléchargement des sources !
Exemple d'utilisation de VSDownloadManager
#import "VSDownloadManager.h"
....
....
- (void) downloadManagerDemo {
VSDownloadManager *downloadManager = [VSDownloadManager getInstance];
// set the delegate that will receive the "
[downloadManager setDelegate:self];
// Empty the current queue
[downloadManager clearItems];
// Adding an element to download
VSDownloadManagerItem *dwlItem = [[VSDownloadManagerItem alloc] initWithURL:@"http://blog.visuaweb.com/public/Images/springboard.jpeg" AndFile:@"/var/root/springboard.jpeg" AndText:nil];
[downloadManager addItem:dwlItem];
[dwlItem release];
// Addning an element to download
VSDownloadManagerItem *dwlItem = [[VSDownloadManagerItem alloc] initWithURL:@"http://blog.visuaweb.com/public/Files/snap_joe.jpg" AndFile:@"/var/root/joe.jpeg" AndText:nil];
[downloadManager addItem:dwlItem];
[dwlItem release];
// Start the download session
[downloadManager start];
}
- (void) VSDownloadManagerDidFinishedDownloadSession:(VSDownloadManager *) sender {
NSLog(@"Download session finiched!");
}
VSDownloadManager.h
//
// VSDownloadManager.h
//
// Created by Jeremie Engel on 28/12/07.
// Copyright 2007 VISUAWEB - http://blog.visuaweb.com. All rights reserved.
//
#import <CoreFoundation/CoreFoundation.h>
#import <Foundation/Foundation.h>
@interface VSDownloadManagerItem : NSObject {
NSString*url;
NSString*filename;
NSString*text;
}
- (id) initWithURL:(NSString*) inURL AndFile:(NSString *) inFilename AndText:(NSString *) inText;
- (NSString *) url;
- (NSString *) filename;
- (NSString *) text;
@end
@interface VSDownloadManager : NSObject {
NSMutableArray*items;
VSDownloadManagerItem * currentItem;
iddelegate;
NSURLConnection*urlConnection;
NSMutableData*receivedData;
intstate;
}
+ (void) initialize;
+ (id) getInstance;
+ (id) allocWithZone:(NSZone *)zone;
- (id) init;
- (void) addItem:(VSDownloadManagerItem *) inItem ;
- (void) clearItems ;
- (void) setDelegate:(id) inDelegate ;
- (void) start ;
@end
VSDownloadManager.m
//
// VSDownloadManager.m
//
// Created by Jeremie Engel on 28/12/07.
// Copyright 2007 VISUAWEB - http://blog.visuaweb.com. All rights reserved.
//
#import "VSLog.h"
#import "VSDownloadManager.h"
@implementation VSDownloadManagerItem
- (id) initWithURL:(NSString*) inURL AndFile:(NSString *) inFilename AndText:(NSString *) inText {
if ((self=[super init])) {
[inURL retain];
url = inURL;
[inFilename retain];
filename = inFilename;
if (inText) {
[inText retain] ;
text = inText;
}
return self;
}
return nil;
}
- (NSString*) url { return url; }
- (NSString*) filename { return filename; }
- (NSString*) text { return text; }
- (NSString *) description {
return url;
}
@end
/*****************************************************************************/
static VSDownloadManager *defaultVSDownloadManager = nil;
@implementation VSDownloadManager
+ (void) initialize { }
+ (id) getInstance {
@synchronized(self) {
if (defaultVSDownloadManager == nil) {
[[self alloc] init]; // assignment not done here
}
}
returndefaultVSDownloadManager;
}
+ (id)allocWithZone:(NSZone *)zone
{
@synchronized(self) {
if (defaultVSDownloadManager == nil) {
defaultVSDownloadManager = [super allocWithZone:zone];
returndefaultVSDownloadManager; // assignment and return on first allocation
}
}
return nil; //on subsequent allocation attempts return nil
}
- (id) init {
NSLog(@"VSDownloadManager initialize");
if ((self=[super init])) {
items = [[NSMutableArray alloc] init];
//receivedData = [[NSMutableData data] retain];
}
returnself;
}
- (void) setDelegate:(id) inDelegate {
if (delegate) [delegate release];
[inDelegate retain];
delegate = inDelegate;
}
- (void) addItem:(VSDownloadManagerItem *) inItem {
if (![items containsObject:inItem]) [items addObject:inItem];
}
- (void) clearItems {
[items removeAllObjects];
}
- (void) start {
NSLog(@"Starting download");
int i;
for (i=0; i<[items count]; i++) {
state = 1;
receivedData = [[NSMutableData alloc] initWithLength: 0];
currentItem = [items objectAtIndex:i];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[currentItem url]] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:5];
urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
while(state == 1) {
[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1f] ];
}
}
if (delegate && [delegate respondsToSelector:@selector(VSDownloadManagerDidFinishedDownloadSession:)]) {
[delegate performSelector:@selector(VSDownloadManagerDidFinishedDownloadSession:) withObject: self];
}
}
/************** NSURLConnection Delegates *****************/
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[receivedData release];
[connection release];
state = -1;
NSLog(@"Connection failed! Error - %@ %@",
[error localizedDescription],
[[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if ([currentItem filename]) [[NSFileManager defaultManager] createFileAtPath:[currentItem filename] contents:receivedData attributes:nil] ;
[connection release];
[receivedData release];
state = 0;
NSLog(@"Download finished for %@", [currentItem url]);
}
/***********************************************************/
- (void) dealloc {
if (receivedData) [receivedData release];
if (urlConnection) [urlConnection release];
[items release];
[superdealloc];
}
@end