Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AFNetworking 3.0 setImageWithURLRequest download progress

Does anyone have a nice working solution for getting the download progress when using the UIImageView+AFNetworking category and AFNetworking 3.0.

This category, which I did use for versions up till 3.0 has stopped working now.

Here is my own experimental version which sadly, for the moment, crashes randomly.

like image 649
knutigro Avatar asked Jan 12 '16 12:01

knutigro


3 Answers

Here is the modified version of AFNetworking 3.0 in which you can show a progress while loading image from server using UIImageView+AFNetworking category.

https://github.com/rushisangani/AFNetworking

Please replace following files with original AFNetworking files.

UIImageView+AFNetworking.h,
UIImageView+AFNetworking.m,

UIImage+ImageDownloader.h,
UIImage+ImageDownloader.m

NOTE: If you update your pod then this will be removed.

like image 194
rushisangani Avatar answered Oct 10 '22 16:10

rushisangani


If you look at AFImageDownloader this, it is used by the UIImageView category to download images. In this class you

- (nullable AFImageDownloadReceipt *)downloadImageForURLRequest:  (NSURLRequest *)request
                                                    success:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse  * _Nullable response, UIImage *responseObject))success
                                                    failure:(nullable void (^)(NSURLRequest *request, NSHTTPURLResponse * _Nullable response, NSError *error))failure;

It returns a receipt which has a NSURLSessionDataTask *task property. NSURLSessionDataTask has different properties of how bytes download, expected bytes to receive etc. Perhaps you can use this and achieve your task.

like image 28
Muhammad Zohaib Ehsan Avatar answered Oct 10 '22 16:10

Muhammad Zohaib Ehsan


You can achieve this by adding few lines in UIImageView+AFNetworking.h

  1. Place this code at top of the file under the import statement

    static void * AFTaskCountOfBytesReceivedContext = &AFTaskCountOfBytesReceivedContext;
    
  2. And you need to register the observer to track the bytes received by adding below line under the function setImageWithURLRequest at the position

    if (cachedImage) {
        // AFNetworking default code
    }
    else{
        // AFNetworking default code
        // Our new lines to track the download
        [self.af_activeImageDownloadReceipt.task addObserver:self forKeyPath:@"state" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesReceivedContext];
        [self.af_activeImageDownloadReceipt.task addObserver:self forKeyPath:@"countOfBytesReceived" options:(NSKeyValueObservingOptions)0 context:AFTaskCountOfBytesReceivedContext];
    }
    
  3. Add this new function at end.

    #pragma mark - NSKeyValueObserving
    
    - (void)observeValueForKeyPath:(NSString *)keyPath
                          ofObject:(id)object
                            change:(__unused NSDictionary *)change
                           context:(void *)context
    {
        if (context == AFTaskCountOfBytesReceivedContext) {
    
            if ([keyPath isEqualToString:NSStringFromSelector(@selector(countOfBytesReceived))]) {
                if ([object countOfBytesExpectedToReceive] > 0) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        //You can do your stuff at here like show progress
                        NSLog(@"Progress : %f",[object countOfBytesReceived] / ([object countOfBytesExpectedToReceive] * 1.0f));
    
                    });
                }
            }
    
            if ([keyPath isEqualToString:NSStringFromSelector(@selector(state))]) {
                if ([(NSURLSessionTask *)object state] == NSURLSessionTaskStateCompleted) {
                    @try {
                        [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(state))];
                        NSLog(@"Image Download Complete");
                        if (context == AFTaskCountOfBytesReceivedContext) {
                            [object removeObserver:self forKeyPath:NSStringFromSelector(@selector(countOfBytesReceived))];
                        }
                    }
                    @catch (NSException * __unused exception) {}
                }
            }
        }
    }
    
like image 37
Jegan Avatar answered Oct 10 '22 14:10

Jegan