Skip to content

Instantly share code, notes, and snippets.

@PaulWoodIII
Last active September 23, 2019 16:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PaulWoodIII/298c185df2ca78f226ba92ba43b3b0cb to your computer and use it in GitHub Desktop.
Save PaulWoodIII/298c185df2ca78f226ba92ba43b3b0cb to your computer and use it in GitHub Desktop.
Obj-C Code needed to show progress of an image downloading using NSURLSession
//
// ImageDownloaderCommonBlocks.h
// AsyncImageDownloader
//
// Created by Paul Wood on 9/23/19.
// Copyright © 2019 Paul Wood. All rights reserved.
//
#ifndef ImageDownloaderCommonBlocks_h
#define ImageDownloaderCommonBlocks_h
typedef void (^ImageCallback)(UIImage * _Nonnull);
typedef void (^ProgressBlock)(NSNumber * _Nonnull);
typedef void (^ImageWithErrorCallback)(NSError * _Nullable, UIImage * _Nullable);
#endif /* ImageDownloaderCommonBlocks_h */
//
// ProgressiveSingleImageDownloader.h
// AsyncImageDownloader
//
// Created by Paul Wood on 9/23/19.
// Copyright © 2019 Paul Wood. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "ImageDownloaderCommonBlocks.h"
NS_ASSUME_NONNULL_BEGIN
@interface ProgressiveSingleImageDownloader : NSObject<NSURLSessionDownloadDelegate>
- (void)downloadBy_NSURLSession:(NSString *)urlString
progress:(ProgressBlock)progressHandler withErrorCallback:(ImageWithErrorCallback) callback;
@end
NS_ASSUME_NONNULL_END
//
// ProgressiveSingleImageDownloader.m
// AsyncImageDownloader
//
// Created by Paul Wood on 9/23/19.
// Copyright © 2019 Paul Wood. All rights reserved.
//
#import "ProgressiveSingleImageDownloader.h"
NSString *TASK_PROGRESS_CONTEXT = @"SingleImageDownloaderTaskProgressChanged";
@interface ProgressiveSingleImageDownloader ()
@property (nonatomic, retain) NSURLSessionDownloadTask* progressiveTask;
@property (nonatomic, retain) NSURLSession* progressiveSession;
@property (nonatomic, copy, nullable) void (^progressBlock)(NSNumber * _Nonnull);
@property (nonatomic, copy, nullable) void (^completionBlock)(NSError * _Nullable, UIImage * _Nullable);
@end
@implementation ProgressiveSingleImageDownloader
- (void)downloadBy_NSURLSession:(NSString *)urlString
progress:(ProgressBlock)progressHandler
withErrorCallback:(ImageWithErrorCallback) callback {
self.progressBlock = progressHandler;
self.completionBlock = callback;
NSURLSessionConfiguration *configuration = NSURLSession.sharedSession.configuration.copy;
self.progressiveSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest* request = [[NSURLRequest alloc] initWithURL:url];
self.progressiveTask = [self.progressiveSession downloadTaskWithRequest:request];
[self.progressiveTask resume];
}
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location {
__block UIImage *img = [UIImage imageWithData: [NSData dataWithContentsOfURL:location]];
dispatch_async(dispatch_get_main_queue(), ^{
__weak typeof (self) weakSelf = self;
weakSelf.completionBlock(nil, img);
});
}
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
double progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite;
NSNumber* progressNum = [NSNumber numberWithDouble:progress];
dispatch_async(dispatch_get_main_queue(), ^{
self.progressBlock(progressNum);
});
}
@end
//
// ViewController.m
// AsyncImageDownloader
//
// Created by Paul Wood on 9/23/19.
// Copyright © 2019 Paul Wood. All rights reserved.
//
#import "ViewController.h"
#import "SingleImageDownloader.h"
#import "ProgressiveSingleImageDownloader.h"
@interface ViewController ()
@property (nonatomic, retain) NSString* urlString;
@property (nonatomic, retain) SingleImageDownloader* imageDownloader;
@property (nonatomic, retain) ProgressiveSingleImageDownloader* progressiveDownloader;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//Setup
self.imageName.text = @"Downloading Image";
self.imageDownloader = [SingleImageDownloader new];
self.progressiveDownloader = [ProgressiveSingleImageDownloader new];
self.urlString = @"https://i.redd.it/4c4slwzhni901.png";
[self.progressView setProgress:0.0 animated:NO];
[self.progressiveDownloader downloadBy_NSURLSession:self.urlString
progress:^(NSNumber * _Nonnull progress) {
__weak typeof (self) weakSelf = self;
[weakSelf.progressView setHidden:NO];
[weakSelf.progressView setProgress:progress.floatValue animated:YES];
weakSelf.imageName.text = [NSString stringWithFormat:@"Downloading Image %@", progress];
}
withErrorCallback:^(NSError * _Nullable err, UIImage * _Nullable img) {
__weak typeof (self) weakSelf = self;
if ( err == nil && img != nil) {
weakSelf.imageView.image = img;
[weakSelf.progressView setHidden:YES];
weakSelf.imageName.text = @"Downloaded Image";
} else if ( err != nil ) {
//handle error
weakSelf.imageName.text = @"Image Download Failed";
}
}];
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment