mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-17 11:00:07 +00:00
On iOS 7, NSURLSessionTask is actually a __NSCFURLSessionTask (private class) and our NSURLSessionTask category to add the associated object asyncdisplaykit_metadata was crashing on iOS 7 stating that there was no method. This commit changes the category to extend NSURLRequest as well as change NSURLSessionTask to NSURLSessionDownloadTask.
157 lines
4.9 KiB
Plaintext
157 lines
4.9 KiB
Plaintext
/* 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 -
|
|
/**
|
|
* NSURLSessionDownloadTask lacks a `userInfo` property, so add this association ourselves.
|
|
*/
|
|
@interface NSURLRequest (ASBasicImageDownloader)
|
|
@property (nonatomic, strong) ASBasicImageDownloaderMetadata *asyncdisplaykit_metadata;
|
|
@end
|
|
|
|
@implementation NSURLRequest (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
|
|
NSURLSessionDownloadTask *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.originalRequest.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:NSURLSessionDownloadTask.class], @"unexpected downloadIdentifier");
|
|
NSURLSessionDownloadTask *task = (NSURLSessionDownloadTask *)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.originalRequest.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.originalRequest.asyncdisplaykit_metadata;
|
|
if (metadata.completionBlock) {
|
|
dispatch_async(metadata.callbackQueue, ^{
|
|
metadata.completionBlock(image.CGImage, nil);
|
|
});
|
|
}
|
|
}
|
|
|
|
// invoked unconditionally
|
|
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionDownloadTask *)task
|
|
didCompleteWithError:(NSError *)error
|
|
{
|
|
ASBasicImageDownloaderMetadata *metadata = task.originalRequest.asyncdisplaykit_metadata;
|
|
if (metadata && error) {
|
|
dispatch_async(metadata.callbackQueue, ^{
|
|
metadata.completionBlock(NULL, error);
|
|
});
|
|
}
|
|
}
|
|
|
|
@end
|