NSURLConnection sendSynchronousRequest - backgroun

2019-03-28 17:53发布

问题:

I m using sendSynchronousRequest to get the data from the server. I know that synchronous will wait until the data received for that request.

But the problem comes when user by mistake enters some non-existing url and than tries to get response. In this case, if user goes in to background and than comes into foreground it shows only black screen. It only shows status bar. Also its not showing any background application. I have to press Home button to come out of my application.

On simulator, After 1+ minute it shows me the message that "Request time out" (No crash).

On Device, within 1 min application get crashes.

Any suggestion. Any Help. This is really a serious issue in my app.

Thanks.

回答1:

Just like Julien said, the watchdog is killing your app. To answer some questions:

  • why does this happen only on the simulator? Because when you're debugging the watchdog leaves your app alone, it can take time.
  • why does this happen only when the user enters a wrong url? Because of the system timeout, the system will keep trying for 60 secs if it can't find a server.
  • so the problem is synchronous vs asynchronous? No, the problem is the thread, you can do the same operation in a background thread, just don't do it on the main thread and the watchdog will leave you alone.
  • why is the screen black when the app comes up? Remember, you are making blocking stuff on the main thread, the thread that draws...

Hope that was all. Let me know if I missed something.



回答2:

Why not setting a timeout for your connection?

NSString *urlString = TEST_CONNECTION;
NSError *error = nil;
NSHTTPURLResponse *response = nil;
NSURLRequest *request = [NSURLRequest
                         requestWithURL:[NSURL URLWithString:urlString]
                         cachePolicy:NSURLRequestReloadIgnoringCacheData
                         timeoutInterval:5.0];


NSData *conn = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

This should release the synchronous waiting after a number of seconds, which should solve your problem without going with an asynchronous call (which sometimes isn't the proper solution)

I know this works properly because this is how I check if I am connected to a certain VPN (where reachability flags totally fail).



回答3:

you should take a look to this article: https://developer.apple.com/library/ios/#qa/qa1693/_index.html

iOs contains a watchdog, if your application is blocked to much time on an operation on the main thread, this one will be killed. (for more details about Watchdog: http://en.wikipedia.org/wiki/Watchdog_timer)

So if you want to download something, don't download it on the main thread.



回答4:

RELATE

UIImage *image = [self.imgCache objectForKey:urlString];
if(!image){
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString] cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:60.0];


    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSURLResponse *response = nil;
        NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
        NSLog(@"%@",response);
        UIImage *img = [UIImage imageWithData:data];
        //

        if(img)
        {
            dispatch_sync(dispatch_get_main_queue(), ^{
                [self.imgCache setObject:img forKey:urlString];
                completionBlock(img);
            });
        }
    });

}
else{
    completionBlock(image);
}


回答5:

use ASIHttpRequest class instead of NSURLConnection , its nothing but wrapper around NSURLConnection and has very simple callbacks , you can also set time to complete a request. Please go through this link for more info http://allseeing-i.com/ASIHTTPRequest/



回答6:

I think you first have to test user data whether it is correct or not and than only if it is correct, sends the request otherwise prompt user that "please enter correct data"...

or

when your parsing of data in response failed. You can also make protocol delegate method i.e FinishWithError so that you come up with your last UI.



回答7:

Try this one:

#import "ASIHTTPRequest.h"

//In a method
[self performSelectorInBackground:@selector(DownLoadImageInBackground:) withObject:imgUrlArr];  


-(void) DownLoadImageInBackground:(NSArray *)imgUrlArr1  
{
    NSURL * url = [Image URL];

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];
    [request startAsynchronous];
}

-(void)requestFailed:(ASIHTTPRequest *)request

{

    NSLog(@"URL Fail : %@",request.url);

    NSError *error = [request error];

       // you can give here alert too..
}

-(void)requestFinished:(ASIHTTPRequest *)request

{

    NSData *responseData = [request responseData];
    UIImage *imgInBackground = [[UIImage alloc]
                         initWithData:responseData];
    [imageView setImage: imgInBackground];

}

This might help you: I am also loading a number of images at one time, so images that have no proper data show a black screen. To avoid this, try to resize your imageview.



回答8:

You could check the reachability of the URL before starting the request. Apple has Reachability Methods to do so. But its easier to use a wrapper. E.g. ASIReachability.



回答9:

I think the application crashing because you does not get any data when user enters wrong URL and you are using this 'returned' nil NSData to do stuffs.

I think this will fix your problem

NSData *data=[NSURLConnection sendSynchronousRequest:request 
                                   returningResponse:&response 
                                               error:&error];
if(data!=nil){
    /// 
} else {
   NSLog(@"NO DATA");
}