1

Hi i am using following code to load the image using NSURLConnection SendAsynchronousRequest call for Tableview but it crashes for IOS 4.3 but same code works for IOS 5.

So can anyone please tell me what changes i have to do support for IOS 4.3

i have gone through below links but nothing worked for me.

NSURLConnection sendAsynchronousRequest:queue:completionHandler not working in iOS 4.3

Have a class called

imagefetcher.h

- (void)fetchImageForURL:(NSURL *)url atIndexPath:(NSIndexPath *)indexPath inTableView:(UITableView *)table;

imagefetcher.m

- (void)fetchImageForURL:(NSURL *)url atIndexPath:(NSIndexPath *)indexPath inTableView:(UITableView *)table {

// NOTE: url is just relative

// There is an issue on iOS 5 that causes the memory capacity to be set to 0 whenever a UIWebView is
// used for the first time. This will correct that issue.
NSLog(@"in fetchImageForURL %@",url);
if([[NSURLCache sharedURLCache] memoryCapacity] != URLMemoryCachSize)
{
    [[NSURLCache sharedURLCache] setMemoryCapacity:URLMemoryCachSize];
}

NSURLRequest *request = [NSURLRequest requestWithURL:url
                                         cachePolicy:NSURLRequestUseProtocolCachePolicy
                                     timeoutInterval:30.0f];


NSCachedURLResponse *cachedResponse = [[NSURLCache sharedURLCache] cachedResponseForRequest:request];
if (cachedResponse)
{
    NSData *data = [cachedResponse data];
    NSLog(@"from cache");
    [self postImageCallbackWithTableView:table atIndexPath:indexPath forURL:url withImageData:data];
}
else
    {
returningResponse:&response error:&error];
//        NSLog(@"loading synchronously");
        [NSURLConnection sendAsynchronousRequest:request
                                           queue:fetcherQueue
                               completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {

                                   [self postImageCallbackWithTableView:table atIndexPath:indexPath forURL:url withImageData:data];

                               }];
//        [self postImageCallbackWithTableView:table atIndexPath:indexPath forURL:url withImageData:data];
    }
}

in tableview controller i am calling follwing method but it crsahes for IOS 4.3 but same works for IOS 5

tableviewcontroller.m

-viewdidload()
{

     [NSURLConnection sendAsynchronousRequest:request queue:fetcherQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                            //[self postImageCallbackWithTableView:table atIndexPath:indexPath forURL:url withImageData:data];
                      UIImage *image = [UIImage imageWithData:data];
                        [self.images setObject:image forKey:index];
                        [table1 beginUpdates];
                        [table1 reloadRowsAtIndexPaths:@[index] withRowAnimation:UITableViewRowAnimationNone];
                        [table1 endUpdates];
                    }];
                }
Community
  • 1
  • 1
Abhilash
  • 638
  • 4
  • 11
  • 28
  • What is the error from the crash? – rmaddy Nov 12 '13 at 17:20
  • it shows Asynchronous request sent to some instance something like this..with synchronous and ios 5 it works fine.. – Abhilash Nov 12 '13 at 17:22
  • 1
    No, update your question with the *exact* error message. – rmaddy Nov 12 '13 at 17:23
  • 3
    Ouch! Do you *really* need to support 4.3!? – David Snabel-Caunt Nov 12 '13 at 17:33
  • The 14,842,324 people using iOS < 5 out of 1,484,232,448 still matter... – Jonathan Nov 12 '13 at 18:20
  • BTW, it's moot since you probably won't be using `sendAsynchronousRequest`, but your above `sendAsynchronousRequest` code samples are trying to do UI updates in the `fetcherQueue`, which, if not the main queue, will be problematic, even in iOS 5+. UI updates should be performed on the main queue. The `queue` parameter is not the queue upon which network operations are performed, but rather the queue on which the completion block executes. – Rob Nov 12 '13 at 18:37

1 Answers1

2

If you look at the documentation for sendAsynchronousRequest, it requires iOS 5. If you need to support iOS 4.3, you'll have to use connectionWithRequest:delegate: or initWithRequest:delegate: and then implement the NSURLConnectionDataDelegate methods (which, while a little more work, offers other advantages such as being able to monitor the progress or cancel the request if you need).

Or, as the answer provided at that other question suggests, write your own method that provides the sendAsynchronousRequest functionality but that actually calls sendSynchronousRequest.

Or, just replace your call with sendAsynchronousRequest:

[NSURLConnection sendAsynchronousRequest:request queue:fetcherQueue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    // do something with `data`, `error`, and `response`
}];

With a call to sendSynchronousRequest that you'll perform on some NSOperationQueue queue. So, first, define a property for your operation queue:

@property (nonatomic, retain) NSOperationQueue *networkQueue;

And then initialize it, for example in viewDidLoad:

self.networkQueue = [[NSOperationQueue alloc] init];
self.networkQueue.name = @"com.domain.app.networkqueue";
self.networkQueue.maxConcurrentOperationCount = 4;

And then you can use that network operation queue to call sendSynchronousRequest:

[self.networkQueue addOperationWithBlock:^{
    NSURLResponse *response = nil;
    NSError *error = nil;
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

    // assuming you want to interact with your UI and or synchronize changes to your model, dispatch this final processing back to the main queue

    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        // do something with `data`, `error`, and `response`
    }];
}];

Bottom line, just replace your calls to sendAsynchronousRequest with methods, such as sendSynchronousRequest, that were available in iOS 4.3.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044