Lazarus
Lazarus

Reputation: 427

Xcode, UIImage is NIL when i trying to implement Load image asynchronously

I trying to implement Load image asynchronously.

    NSURL *url = [NSURL URLWithString:_posterImg];
    NSURLRequest* request = [NSURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse * response,
                                               NSData * data,
                                               NSError * error) {
                               if (!error){
                                   UIImage *getImg = [[UIImage alloc] initWithData:data];
                                   // do whatever you want with image
                               }

                           }];

But when i put this code, getImg will get warning "Unused Variable". i had check "response", "data" and "error", it all look fine but the getImg is NIL. is that i had write any thing wrong? thanks.

Upvotes: 0

Views: 184

Answers (1)

MABVT
MABVT

Reputation: 1360

The affected variable is response. Although you use data and error, response is only declared as a parameter but nowhere used in your completion handler!

NSURL *url = [NSURL URLWithString:_posterImg];
NSURLRequest* request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
                                   queue:[NSOperationQueue mainQueue]
                       completionHandler:^(NSURLResponse * response,
                                           NSData * data,
                                           NSError * error) {
                           NSString *errorMsg = nil;
                           UIImage *getImg = nil;
                           if (!error){
                               getImg = [[UIImage alloc] initWithData:data];
                           }
                           else 
                           {
                              errorMsg = [NSString stringWithFormat:@"Failed to load image. Error Message: %@", [error localizedString]];
                           }                              

                           [self handleImageRequestWithResponse:response image:getImg andErrorMessage:errorMsg];

                       }];
// Image hasn't load yet here since the request is asynchronously!
//if(getImg != nil && errorMsg == nil)
//    NSLog(@"Image is available!");
//else 
//    NSLog(@"Loading the image asynchronously failed! %@", errorMsg);


// In addition now provide the following method.
- (void) handleImageRequestWithResponse:(NSURLResponse*)response image:(UIImage*)img andErrorMessage:(NSString*)err
{
    if(img!= nil && err == nil)
        NSLog(@"Image is available!");
    else 
        NSLog(@"Loading the image asynchronously failed! %@", err);

    // Handle image
};

EDIT: My bad! Since the code executes asynchronously getImg was of course nil when you checked as before


EDIT:

Using NSData dataWithContentsOfURL is synchronous,i.e. if executed on the main thread your application is blocked. See this official documentation: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSData_Class/Reference/Reference.html#//apple_ref/occ/clm/NSData/dataWithContentsOfURL:

Most important:

Important: Do not use this synchronous method to request network-based URLs. For network-based URLs, this method can block the current thread for tens of seconds on a slow network, resulting in a poor user experience, and in iOS, may cause your app to be terminated.

Going for a completionHandler and a handler method called after the requested raw data has been handled/prepared is better for your performance and does not violate the official recommendation!

Upvotes: 1

Related Questions