简体   繁体   中英

NSURLConnection delegate methods not being called

I'm trying to use the delegate methods of NSURLConnection. The following methods are currently not being called:

- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;

- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge;
//I also want to be able to use self-signed https urls

- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace;
//I also want to be able to use self-signed https urls

I'm currently using a synchronous call but asynchronous seems better because after I complete the code base I'm going to implement it into an iPhone application and I can't have my ui freezing.

With the following method responseData = [NSMutableData dataWithData:[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]];

I get back the data I need but using asynchronous I seems I have to use the delegate methods to get data back. I tried to add the delegate by using @interface myClass : NSObject<NSURLConnectionDelegate>

I'm calling my method as follows:

-(void)grabData{
    NSArray* array = [NSArray arrayWithObjects:@"auth.login",@"user",@"pass", nil];
    NSData* packed_array = [array messagePack];

    NSURL* url = [NSURL URLWithString:@"https://192.168.1.115:3790/"];
    NSMutableURLRequest* request = [[[NSMutableURLRequest alloc]initWithURL:url]retain];
    [request setHTTPMethod:@"POST"];
    [request setValue:@"RPC Server" forHTTPHeaderField:@"Host"];
    [request setValue:@"binary/message-pack" forHTTPHeaderField:@"Content-Type"];
    [request setValue:[NSString stringWithFormat:@"%d",[packed_array length]] forHTTPHeaderField:@"Content-Length"];
    [request setHTTPBody:packed_array];

    //NSHTTPURLResponse *response = nil;
    NSError *error = nil;

    NSLog(@"connecting");
    NSURLConnection* connection = [[[NSURLConnection alloc]initWithRequest:request delegate:self]retain];
    if (connection) {
        NSLog(@"connection exists");
        self.responseData = [[NSMutableData data]retain];
    }
    else {
        NSLog(@"Connection doesn't exist?");
    }
    NSLog(@"response data: %@",[responseData messagePackParse]);
    NSLog(@"error: %@",error);
}

I've attempted the following:

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

I continued to search for related questions and found this answer most helpful . It lead me to using the following method. First I declared a BOOL property called finished in my interface and added the following method in my implementation which caused my delegate methods to be called.

while(!finished) {
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}

Just a thought- any chance you're using Automatic Reference Counting and the object that is creating the NSURLConnection is being deallocated between the time you call [connection start] and when the delegate methods should be called (ie, data has been received)?

Does anything maintain a reference to the object you're using to create the NSURLConnection?

Based on additional information, it does seem like this is a likely cause. You likely have code such as the following in your App Delegate (or another class you've created).

MyClass *object = [[MyClass alloc] init];
[object grabData];

This is great- it instantiates an object and then tells that object to grab the data in question. But, once grabData completes (and before the NSURLConnection returns data), object will be deallocated because nothing is holding on to it. To fix this:

  1. Create a property in your .h file (where you create the object) to hold onto your instance of MyClass.

    @property (strong) MyClass *object;

  2. Synthesize that property in your .m file

    @synthesize object;

  3. Rather than just creating your object, hold a reference to it:

    MyClass *myClass = [[MyClass alloc] init];

    [myClass grabData];

    self.object = myClass;

This will prevent your object from being deallocated by ARC.

When you're totally done with the object (your NSURLConnection has returned data), you can set self.object = nil to get rid of that reference.

You can use this:

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest: request delegate:self startImmediately:NO];

[connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

[connection start];

If you're having trouble you can do what I've done in the past and use synchronous requests like so:

NSHTTPURLResponse *response = nil;
NSError *error = nil;
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]

This will output the data you need, all you need to do for it to not lock up your UI is use a block (GCD):

dispatch_queue_t downloadQueue = dispatch_queue_create("download queue", NULL);
dispatch_async(downloadQueue, ^{
  NSHTTPURLResponse *response = nil;
  NSError *error = nil;
  NSData *myData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]
  dispatch_async(dispatch_get_main_queue(), ^{
    // Handle your response data
  });
});

After establishing the connection just write below

[connection start]; your delegate method will be called.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM