Permalink
Browse files

Added Pie Progress Indicator

  • Loading branch information...
odrobnik committed May 21, 2012
1 parent 9f9da74 commit d7293c386ba4f8621791f29d1a217603bd26cb32
View
@@ -1,15 +1,24 @@
//
-// CatalogDownloader.h
-// iCatalog
+// DTDownload.h
+// DTFoundation
//
// Created by Oliver Drobnik on 8/6/10.
// Copyright 2010 Drobnik.com. All rights reserved.
//
-#import <Foundation/Foundation.h>
+// notifications
+extern NSString * const DTDownloadProgressNotification;
+
@class DTDownload;
+// block-based response handler, called after headers were received
+typedef void (^DTDownloadResponseHandler)(DTDownload *, NSDictionary *headers);
+
+// block-based completion handler, called once the download has finished
+typedef void (^DTDownloadCompletionHandler)(DTDownload *);
+
+
/**
Methods that a delegate of a download object is being queried with.
*/
@@ -150,4 +159,19 @@
- (BOOL)isLoading;
+/**-------------------------------------------------------------------------------------
+ @name Block Handlers
+ ---------------------------------------------------------------------------------------
+ */
+
+/**
+ Sets the block to execute as soon as the HTTP response has been received.
+ */
+@property (nonatomic, copy) DTDownloadResponseHandler responseHandler;
+
+/**
+ Sets the block to execute as soon as the download has completed.
+ */
+@property (nonatomic, copy) DTDownloadCompletionHandler completionHandler;
+
@end
View
@@ -9,6 +9,8 @@
#import "DTDownload.h"
#import "NSString+DTUtilities.h"
+NSString * const DTDownloadProgressNotification = @"DTDownloadProgressNotification";
+
@interface DTDownload ()
@property (nonatomic, retain) NSString *internalDownloadFolder;
@@ -50,6 +52,9 @@ @implementation DTDownload
BOOL headOnly;
BOOL _isLoading;
+
+ // response handlers
+ DTDownloadResponseHandler _responseHandler;
}
#pragma mark Downloading
@@ -97,7 +102,7 @@ - (void)startWithResume:(BOOL)shouldResume
{
_isLoading = YES;
- NSString *fileName = [[_URL absoluteString] md5Checksum];
+ NSString *fileName = [[_URL path] lastPathComponent];
self.internalDownloadFolder = [[self.folderForDownloading stringByAppendingPathComponent:fileName] stringByAppendingPathExtension:@"download"];
receivedDataFilePath = [internalDownloadFolder stringByAppendingPathComponent:fileName];
@@ -120,9 +125,6 @@ - (void)startWithResume:(BOOL)shouldResume
downloadEntryIdentifier = [NSString stringWithUUID];
}
- downloadEntityTag = [resumeInfo objectForKey:@"NSURLDownloadEntityTag"];
-
-
if ([delegate respondsToSelector:@selector(shouldResumeDownload:)])
{
if (!shouldResume || ![delegate shouldResumeDownload:self])
@@ -140,6 +142,9 @@ - (void)startWithResume:(BOOL)shouldResume
if (shouldResume)
{
+ downloadEntityTag = [resumeInfo objectForKey:@"NSURLDownloadEntityTag"];
+
+
// here we assume we should continue download
receivedDataFile = [NSFileHandle fileHandleForWritingAtPath:receivedDataFilePath];
[receivedDataFile seekToEndOfFile];
@@ -170,20 +175,27 @@ - (void)startWithResume:(BOOL)shouldResume
{
if (receivedBytes && receivedBytes == _totalBytes)
{
- NSLog(@"Already done!");
-
+ // Already done!
[self _completeDownload];
return;
}
}
}
+ else
+ {
+ // reset
+ receivedBytes = 0;
+ _totalBytes = 0;
+ downloadEntityTag = nil;
+ lastModifiedDate = nil;
+ }
}
else
{
// create download folder
NSError *error = nil;
- if (![[NSFileManager defaultManager] createDirectoryAtPath:internalDownloadFolder withIntermediateDirectories:NO attributes:nil error:&error])
+ if (![[NSFileManager defaultManager] createDirectoryAtPath:internalDownloadFolder withIntermediateDirectories:YES attributes:nil error:&error])
{
NSLog(@"Cannot create download folder %@, %@", internalDownloadFolder, [error localizedDescription]);
return;
@@ -192,8 +204,6 @@ - (void)startWithResume:(BOOL)shouldResume
downloadEntryIdentifier = [NSString stringWithUUID];
}
-
-
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:_URL
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:60.0];
@@ -268,6 +278,11 @@ - (void)_completeDownload
{
[delegate download:self didFinishWithFile:targetPath];
}
+
+ if (_completionHandler)
+ {
+ _completionHandler(self);
+ }
}
- (void)_updateDownloadInfo
@@ -359,8 +374,6 @@ - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLRespon
}
}
-
-
// get something to identify file
NSString *modified = [http.allHeaderFields objectForKey:@"Last-Modified"];
if (modified)
@@ -373,6 +386,10 @@ - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLRespon
lastModifiedDate = [dateFormatter dateFromString:modified];
}
+ if (_responseHandler)
+ {
+ _responseHandler(self, [http allHeaderFields]);
+ }
}
else
{
@@ -415,20 +432,27 @@ - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
self.lastPaketTimestamp = now;
-
// notify delegate
if ([delegate respondsToSelector:@selector(download:downloadedBytes:ofTotalBytes:withSpeed:)])
{
[delegate download:self downloadedBytes:receivedBytes ofTotalBytes:_totalBytes withSpeed:downloadSpeed];
}
+
+ // send notification
+ if (_totalBytes)
+ {
+ NSDictionary *userInfo = [NSDictionary dictionaryWithObject:[NSNumber numberWithFloat:(float)receivedBytes / (float)_totalBytes] forKey:@"ProgressPercent"];
+ [[NSNotificationCenter defaultCenter] postNotificationName:DTDownloadProgressNotification object:self userInfo:userInfo];
+ }
}
-
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
receivedData = nil;
urlConnection = nil;
-
+
+ _isLoading = NO;
+
[receivedDataFile closeFile];
if (headOnly)
@@ -442,8 +466,6 @@ - (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[self _completeDownload];
}
-
- _isLoading = NO;
}
#pragma mark Notifications
@@ -457,7 +479,9 @@ - (NSString *)folderForDownloading
{
if (!folderForDownloading)
{
- self.folderForDownloading = NSTemporaryDirectory();
+ NSString *md5 = [[_URL absoluteString] md5Checksum];
+
+ self.folderForDownloading = [NSTemporaryDirectory() stringByAppendingPathComponent:md5];
}
return folderForDownloading;
@@ -472,6 +496,8 @@ - (BOOL)isLoading
@synthesize MIMEType = _MIMEType;
@synthesize totalBytes = _totalBytes;
@synthesize context;
+@synthesize responseHandler = _responseHandler;
+@synthesize completionHandler = _completionHandler;
@end
@@ -10,6 +10,16 @@
extern NSString *DTDownloadCacheDidCacheFileNotification;
+
+enum {
+ DTDownloadCacheOptionNeverLoad = 0,
+ DTDownloadCacheOptionLoadIfNotCached,
+ DTDownloadCacheOptionReturnCacheAndLoadAlways,
+ DTDownloadCacheOptionReturnCacheAndLoadIfChanged,
+};
+typedef NSUInteger DTDownloadCacheOption;
+
+
@interface DTDownloadCache : NSObject <DTDownloadDelegate>
/**
@@ -20,10 +30,10 @@ extern NSString *DTDownloadCacheDidCacheFileNotification;
/**
@param URL The URL of the file
- @param shouldLoad If the data should be loaded from the web in case it is not cached already.
+ @param option A loading option to specify wheter the file should be loaded if it is already cached.
@returns The cached image or `nil` if none is cached.
*/
-- (NSData *)cachedDataForURL:(NSURL *)URL shouldLoad:(BOOL)shouldLoad;
+- (NSData *)cachedDataForURL:(NSURL *)URL option:(DTDownloadCacheOption)option;
/**
current sum of cached files in Bytes
@@ -52,9 +62,9 @@ extern NSString *DTDownloadCacheDidCacheFileNotification;
/**
Specialized method for retrieving cached images.
@param URL The URL of the image
- @param shouldLoad If the image should be loaded from the web in case it is not cached already.
+ @param option A loading option to specify wheter the file should be loaded if it is already cached.
@returns The cached image or `nil` if none is cached.
*/
-- (UIImage *)cachedImageForURL:(NSURL *)URL shouldLoad:(BOOL)shouldLoad;
+- (UIImage *)cachedImageForURL:(NSURL *)URL option:(DTDownloadCacheOption)option;
@end
Oops, something went wrong.

0 comments on commit d7293c3

Please sign in to comment.