NSUrlConnectionDelegate not calling methods to loa

2019-08-26 11:11发布

I have looked at NSURLConnectionDelegate connection:didReceiveData not working already, but there didn't seem to be any good result from that, so I am curious why I am not able to get any data.

I put in breakpoints in didReceiveResponse and didReceiveData.

It does print out "connection succeeded", so I know that the connection is started.

I am using ARC for memory management.

- (void)load {
        request = [NSMutableURLRequest requestWithURL:myURL
                                                           cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                                       timeoutInterval:60];

    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (conn) {
        [conn start];
        NSLog(@"connection succeeded, %s", [myURL description]);  
        responseData = [NSMutableData data];
    } else {
        NSLog(@"connection failed");
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    responseData = [[NSMutableData alloc] init];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [responseData appendData:data];
}

UPDATE:

To see how I test this look at Asynchronous unit test not being called by SenTestCase.

I did implement the two methods mentioned by jonkroll, in his answer, I just didn't show them, but, they also aren't being called.

I had added [conn start] only because it wasn't working, and I was hoping that may solve it, but no such luck.

2条回答
【Aperson】
2楼-- · 2019-08-26 11:41

When you declare your connection like this:

NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];

You are creating a local pointer. When your method completes, since it was the last strong reference to the NSURLConnection, ARC releases it. You need to use a strong ivar (and/or) property to hold a strong reference to the NSURLConnection you create.

Edit

Here is basic sample of code that I tested in a sample project. Give it a run. Verbose logging helps.

@implementation <#Your class here#> {
    // With ARC ivars are strong by default 
    NSMutableData *_downloadedData;
    NSURLConnection *_connection;
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    NSHTTPURLResponse *realResponse = (NSHTTPURLResponse *)response;
    if (realResponse.statusCode == 200){ 
        // Really any 2** but for example
        _downloadedData = [[NSMutableData alloc] init];
        NSLog(@"Good response");
    } else {
        NSLog(@"Bad response = %i",realResponse.statusCode);
    }
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    if (connection == _connection){
        [_downloadedData appendData:data];
        NSLog(@"Getting data...");
    }
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
    if (connection == _connection){
        _connection = nil;
        NSLog(@"We're done, inform the UI or the delegates");
    }
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    _connection = nil;
    NSLog(@"Oh no! Error:%@",error.localizedDescription);
}
- (void)load {
    NSURL *url = [NSURL URLWithString:@"http://www.google.com/"];
    NSURLRequest *request = [NSMutableURLRequest requestWithURL:url
                                      cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
                                  timeoutInterval:60];
    // Assign strong pointer to new connection
    _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    NSLog(@"Connection was initialized? = %@",(!!_connection)?@"YES":@"NO");
}
@end
查看更多
疯言疯语
3楼-- · 2019-08-26 11:53

The NSURLConnection method initWithRequest starts an asynchronous request for data from a url. Because the request is done asynchronously you can't expect to work with the response in the same method in which the request is invoked. Instead you need to do so in the NSURLConnection's delegate callback methods. You have already implemented didReceiveResponse: and didReceiveData:, but there are a couple others that will be useful to you.

If you want to look at the contents of the response you should do so in connectionDidFinishLoading:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // response is complete, do something with the data
    NSLog(@"%@", responseData);
}

The fact that your code prints out "connection succeeded" doesn't really mean that the request was successful, only that the NSURLConnection object was created successfully. To test whether there was a problem with the connection you can implement the delegate method connection:didFailWithError:

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

Also there is no need to call [conn start]. The request will be started automatically when you call initWithRequest:

I suggest reading Apple's documentation on Using NSURLConnection for more details.

查看更多
登录 后发表回答