mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-24 07:05:35 +00:00
ASBasicImageDownloader.
This is a simplistic, NSURLSession-based downloader object that implements ASImageDownloaderProtocol and can be used with ASMultiplexImageNode and ASNetworkImageNode. (Closes #115. NSURLSession should suffice for most usecases, and this code should provide a good jumping-off point for a more-complex implementation.)
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
#import <AsyncDisplayKit/ASImageNode.h>
|
||||
#import <AsyncDisplayKit/ASTextNode.h>
|
||||
|
||||
#import <AsyncDisplayKit/ASBasicImageDownloader.h>
|
||||
#import <AsyncDisplayKit/ASMultiplexImageNode.h>
|
||||
#import <AsyncDisplayKit/ASNetworkImageNode.h>
|
||||
|
||||
|
||||
16
AsyncDisplayKit/Details/ASBasicImageDownloader.h
Normal file
16
AsyncDisplayKit/Details/ASBasicImageDownloader.h
Normal file
@@ -0,0 +1,16 @@
|
||||
/* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import <AsyncDisplayKit/ASImageProtocols.h>
|
||||
|
||||
/**
|
||||
* @abstract Simple NSURLSession-based image downloader.
|
||||
*/
|
||||
@interface ASBasicImageDownloader : NSObject <ASImageDownloaderProtocol>
|
||||
|
||||
@end
|
||||
156
AsyncDisplayKit/Details/ASBasicImageDownloader.mm
Normal file
156
AsyncDisplayKit/Details/ASBasicImageDownloader.mm
Normal file
@@ -0,0 +1,156 @@
|
||||
/* Copyright (c) 2014-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
|
||||
#import "ASBasicImageDownloader.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "ASThread.h"
|
||||
|
||||
|
||||
#pragma mark -
|
||||
/**
|
||||
* Collection of properties associated with a download request.
|
||||
*/
|
||||
@interface ASBasicImageDownloaderMetadata : NSObject
|
||||
@property (nonatomic, strong) dispatch_queue_t callbackQueue;
|
||||
@property (nonatomic, strong) void (^downloadProgressBlock)(CGFloat);
|
||||
@property (nonatomic, strong) void (^completionBlock)(CGImageRef, NSError *);
|
||||
@end
|
||||
|
||||
@implementation ASBasicImageDownloaderMetadata
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark -
|
||||
/**
|
||||
* NSURLSessionTask lacks a `userInfo` property, so add this association ourselves.
|
||||
*/
|
||||
@interface NSURLSessionTask (ASBasicImageDownloader)
|
||||
@property (nonatomic, strong) ASBasicImageDownloaderMetadata *asyncdisplaykit_metadata;
|
||||
@end
|
||||
|
||||
@implementation NSURLSessionTask (ASBasicImageDownloader)
|
||||
static const char *kMetadataKey = NSStringFromClass(ASBasicImageDownloaderMetadata.class).UTF8String;
|
||||
- (void)setAsyncdisplaykit_metadata:(ASBasicImageDownloaderMetadata *)asyncdisplaykit_metadata
|
||||
{
|
||||
objc_setAssociatedObject(self, kMetadataKey, asyncdisplaykit_metadata, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
- (ASBasicImageDownloader *)asyncdisplaykit_metadata
|
||||
{
|
||||
return objc_getAssociatedObject(self, kMetadataKey);
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark -
|
||||
@interface ASBasicImageDownloader () <NSURLSessionDownloadDelegate>
|
||||
{
|
||||
NSOperationQueue *_sessionDelegateQueue;
|
||||
NSURLSession *_session;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation ASBasicImageDownloader
|
||||
|
||||
#pragma mark Lifecycle.
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (!(self = [super init]))
|
||||
return nil;
|
||||
|
||||
_sessionDelegateQueue = [[NSOperationQueue alloc] init];
|
||||
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
|
||||
delegate:self
|
||||
delegateQueue:_sessionDelegateQueue];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark ASImageDownloaderProtocol.
|
||||
|
||||
- (id)downloadImageWithURL:(NSURL *)URL
|
||||
callbackQueue:(dispatch_queue_t)callbackQueue
|
||||
downloadProgressBlock:(void (^)(CGFloat))downloadProgressBlock
|
||||
completion:(void (^)(CGImageRef, NSError *))completion
|
||||
{
|
||||
// create download task
|
||||
NSURLSessionTask *task = [_session downloadTaskWithURL:URL];
|
||||
|
||||
// associate metadata with it
|
||||
ASBasicImageDownloaderMetadata *metadata = [[ASBasicImageDownloaderMetadata alloc] init];
|
||||
metadata.callbackQueue = callbackQueue ?: dispatch_get_main_queue();
|
||||
metadata.downloadProgressBlock = downloadProgressBlock;
|
||||
metadata.completionBlock = completion;
|
||||
task.asyncdisplaykit_metadata = metadata;
|
||||
|
||||
// start downloading
|
||||
[task resume];
|
||||
|
||||
// return the task as an opaque cancellation token
|
||||
return task;
|
||||
}
|
||||
|
||||
- (void)cancelImageDownloadForIdentifier:(id)downloadIdentifier
|
||||
{
|
||||
if (!downloadIdentifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASDisplayNodeAssert([downloadIdentifier isKindOfClass:NSURLSessionTask.class], @"unexpected downloadIdentifier");
|
||||
NSURLSessionTask *task = (NSURLSessionTask *)downloadIdentifier;
|
||||
|
||||
[task cancel];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark NSURLSessionDownloadDelegate.
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
|
||||
didWriteData:(int64_t)bytesWritten
|
||||
totalBytesWritten:(int64_t)totalBytesWritten
|
||||
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
|
||||
{
|
||||
ASBasicImageDownloaderMetadata *metadata = downloadTask.asyncdisplaykit_metadata;
|
||||
if (metadata.downloadProgressBlock) {
|
||||
metadata.downloadProgressBlock((CGFloat)totalBytesWritten / (CGFloat)totalBytesExpectedToWrite);
|
||||
}
|
||||
}
|
||||
|
||||
// invoked if the download succeeded with no error
|
||||
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
|
||||
didFinishDownloadingToURL:(NSURL *)location
|
||||
{
|
||||
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
|
||||
|
||||
ASBasicImageDownloaderMetadata *metadata = downloadTask.asyncdisplaykit_metadata;
|
||||
if (metadata.completionBlock) {
|
||||
dispatch_async(metadata.callbackQueue, ^{
|
||||
metadata.completionBlock(image.CGImage, nil);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// invoked unconditionally
|
||||
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
|
||||
didCompleteWithError:(NSError *)error
|
||||
{
|
||||
ASBasicImageDownloaderMetadata *metadata = task.asyncdisplaykit_metadata;
|
||||
if (metadata && error) {
|
||||
dispatch_async(metadata.callbackQueue, ^{
|
||||
metadata.completionBlock(NULL, error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user