1

I created a small solution for downloading any kind of file and then save the that to Cache.db. Everything is working perfectly so far but now i want to create a Wrapper Class for this class so i can convert the Nsdata to any format i want

#import "DownLoadFiles.h"

@implementation DownLoadFiles
@synthesize task,session,dataType;


-(void)DownloadCacheFile:(NSURLRequest*)urlRequest callBackBlock:(void (^)(id))responeBlock{
    NSURLSession *sessions = [NSURLSession sharedSession];
    NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:urlRequest];

    if ([cachedResponse isKindOfClass:[NSNull class]]||cachedResponse==nil) {

        NSLog(@"cachedResponse -- %@",[cachedResponse response]);


        NSURLSessionDataTask *tasked=   [sessions dataTaskWithRequest:urlRequest
                                                    completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                                                            responeBlock(data);
                                                    }];
        [tasked resume];


    }else{
        switch (urlRequest.cachePolicy) {
            case NSURLRequestUseProtocolCachePolicy:
            case NSURLRequestReturnCacheDataElseLoad:
            case NSURLRequestReturnCacheDataDontLoad: {

                    responeBlock([cachedResponse data]);
                break;
            }
            default:
                break;
        }
    }
}

@end

for instance that i know the url contain image so i want to convert the NSData to UIImage so same as for the rest of the format Types like json, avi, etc. like this.

@implementation AKImage
@synthesize image;

-(UIImage*)SetImageforUrl:(NSURLRequest*)imgRequest {
    UIImage *image;

       DownLoadFiles*dwnl=[[DownLoadFiles alloc] init];
        [dwnl DownloadCacheFile:req
                  callBackBlock:^(id response) {
           image=  [UIImage imageWithData:response];

       }];
    return image;
}

@end

so the problem starts here. i want to return the image but image will not wait for the lazy method to return the data, so it is returning nil and after some time block has data.

at my viewController i want to use AKImage wrapper Class like this

AKImage *akObj=[[AKImage alloc] init];
self.imgView.image=[akObjt SetImageforUrl:req];

but currently this block does not allow me to do that

James Z
  • 12,209
  • 10
  • 24
  • 44
AFTAB MUHAMMED KHAN
  • 2,189
  • 3
  • 18
  • 24
  • Don't do this. You need to write your code to properly deal with the fact that getting the image can take a long time. – rmaddy Nov 20 '16 at 19:16
  • like how i deal with that any suggestion – AFTAB MUHAMMED KHAN Nov 20 '16 at 19:17
  • its a block method and its working fine i dont understand how i can achieve that like just writing self.imgView.image get the image i dont mind if it take bit of time just i want to cache them and once it cache it should set into the imageview – AFTAB MUHAMMED KHAN Nov 20 '16 at 19:20

1 Answers1

1

You need to add a custom callback to your method so it will call when the download callback is called.

-(void)imageforUrl:(NSURLRequest*)imgRequest completion:(void (^)(UIImage *image))handler {

    DownLoadFiles *dwnl = [[DownLoadFiles alloc] init];

    [dwnl DownloadCacheFile:req callBackBlock:^(id response) {

        // Update UI on the main queue
        dispatch_async(dispatch_get_main_queue(), ^{
            handler([UIImage imageWithData:response]);
        });
    }];
}

Then call it like this:

AKImage *akObj = [[AKImage alloc] init];
[akObjt imageforUrl: req completion:^(UIImage *image) {
    self.imgView.image = image
}];

Been awhile since I wrote some Objective-C, please double check the syntax yourself.

Edit:

To make a class method: What is the difference between class and instance methods?

Community
  • 1
  • 1
Frankie
  • 11,508
  • 5
  • 53
  • 60
  • 1
    1) Why Is the method named `setImageforUrl:completion:`? It doesn't set anything. 2) What is that unused `image` variable? 3) The image needs to be set on the main queue. – rmaddy Nov 20 '16 at 19:27
  • yes you are right i used this approach but in the end i just want a less code in this side – AFTAB MUHAMMED KHAN Nov 20 '16 at 19:27
  • AKImage *akObj = [[AKImage alloc] init]; [akObjt setImageforUrl: req completion:^(UIImage *image) { self.imgView.image = image }]; – AFTAB MUHAMMED KHAN Nov 20 '16 at 19:27
  • i want something class method like self.imgView.image [AKImage setImageforUrl: req]; like [UIColor redColor] do – AFTAB MUHAMMED KHAN Nov 20 '16 at 19:29
  • @rmaddy Thanks for the constructive review, I started by copying exactly what he had, but your suggestions were necessary. – Frankie Nov 20 '16 at 19:34
  • 1
    @aftabmuhammedkhan Then make `imageForUrl` a class method instead of an instance method. – Frankie Nov 20 '16 at 19:35
  • @Frankie is there any way i can directly assign value rather then using completion block [akObjt imageforUrl: req completion:^(UIImage *image) { self.imgView.image = image }]; i want use of this class should be easy rather that writing 3 line code to just assinging image – AFTAB MUHAMMED KHAN Nov 20 '16 at 19:46