Downloader.h
Downloader.m
// Private implementation interface @interface Downloader () // The thread/queue on which all downloads take place @property (readwrite, atomic) dispatch_queue_t downloadQueue; // A cache of previously downloaded URLs @property (readwrite, atomic) NSMutableDictionary *cachedDownloads; // Download the contents of a URL and cache them - (NSData *)downloadAndCacheUrl:(NSString *)URLString; @end // Implementation @implementation Downloader // Create the download queue and cache - (id)init { self = [super init]; if (self) { downloadQueue = dispatch_queue_create("downloadQueue", NULL); self.cachedDownloads = [NSMutableDictionary dictionary]; } return self; } // Download the URL aynchronously on the download queue. // When the download completes pass the result to the callback queue // by calling downloadCompleted on the callback queue - (void)download:(NSString *)URLString calbackQueue:(dispatch_queue_t)callbackQueue completionBlock:(DownloadCompletedBlock)downloadCompleted { dispatch_async(self.downloadQueue, ^{ NSData *downloadedData = [self downloadAndCacheUrl:URLString]; dispatch_async(callbackQueue, ^{ downloadCompleted(downloadedData); }); }); } // Download the data blocking the calling thread // Use a block variable to store the result // Since the downloaded data is immutable, we do not need // to worry about synchronizing it or copying it // Use dispatch_sync to wait until the result is available // If the data is already in the cache because thread A downloaded it // then the cached data is used. // Since downloads happen serially, there is only ever one download happening // at a time so the download will only happen once - (NSData *)downloadBlocking:(NSString *)URLString { __block NSData *downloadedData = nil; dispatch_sync(self.downloadQueue, ^{ downloadedData = [self downloadAndCacheUrl:URLString]; }); return downloadedData; } // Download the content of a URL. If the data has already been // downloaded and cached, then use the cached value - (NSData *)downloadAndCacheUrl:(NSString *)URLString { NSURL *URL = [NSURL URLWithString:*)URLString]; NSData *downloadedData = [self.cachedDownloads objectForKey:URL]; if (downloadedData) { return downloadedData; } downloadedData = [NSData dataWithContentsOfURL:URL]; if (downloadedData) { [self.cachedDownloads setObject:downloadedData forKey:URL]; } } @end
Hope this is clear enough
source share