Reputation: 7560
I spent a lot of time for research on POST Requests using Cocoa.
I found some code that looked good. I changed it like it fits my needs. But the code didn't work and I can't find the bug because I'm pretty new to cocoa.
Here is my code.
- (IBAction)sendForm:(id)sender
{
NSLog(@"web request started");
NSString *post = [NSString stringWithFormat:@"firstName=%@&lastName=%@&eMail=%@&message=%@", firstName.stringValue, lastName.stringValue, eMail.stringValue, message.stringValue];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:@"%d", [postData length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:@"myDomain/form.php"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if(theConnection)
{
webData = [[NSMutableData data] retain];
NSLog(@"connection initiated");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[webData appendData:data];
NSLog(@"connection received data");
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSLog(@"connection received response");
NSHTTPURLResponse *ne = (NSHTTPURLResponse *)response;
if([ne statusCode] == 200)
{
NSLog(@"connection state is 200 - all okay");
NSString *html = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
[[webView mainFrame] loadHTMLString:html baseURL:[NSURL URLWithString:@"myDomain"]];
}
}
But the only two NSLog messages I receive are "web request started" and "connection initiated".
So I think - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
and - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
are not called.
Can anybody help me with this issue?
Thanks for help, Julian
Upvotes: 1
Views: 5268
Reputation: 9570
You almost did it correctly!
I can see the post is a year old but in the hope that it may help others and for my own reference, I am posting this here.
Apple's documentation for connection:didReceiveResponse:
says :-
Sent when the connection has received sufficient data to construct the URL response for its request.
As with most Apple documentation this too is confusing and maybe misleading. Usually when we have "sufficient data to construct the URL response" means we have the complete response which further means that we have response body too; which is universally considered part of the response.
However in this case the NSHTTPURLResponse
object does not have a body. So my guess is, what Apple means is - connection:didReceiveResponse:
is invoked when we have received the response header which has "sufficient" data to let us known everything about the response, except the actual data (body).
In fact many times you will notice that connection:didReceiveData:
gets called after connection:didReceiveResponse:
is invoked.
So, we can modify your code as below :-
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSLog(@"web request started");
NSString *post = [NSString stringWithFormat:@"firstName=%@&lastName=%@&eMail=%@&message=%@", firstName.stringValue, lastName.stringValue, eMail.stringValue, message.stringValue];
NSData *postData = [post dataUsingEncoding:NSUTF8StringEncoding];
NSString *postLength = [NSString stringWithFormat:@"%ld", (unsigned long)[postData length]];
NSLog(@"Post data: %@", post);
NSMutableURLRequest *request = [NSMutableURLRequest new];
[request setURL:[NSURL URLWithString:@"https://example.com/form.php"]];
[request setHTTPMethod:@"POST"];
[request setValue:postLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:postData];
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if(theConnection) {
webData = [NSMutableData data];
NSLog(@"connection initiated");
}
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[webData appendData:data];
NSLog(@"connection received data");
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(@"connection received response");
NSHTTPURLResponse *ne = (NSHTTPURLResponse *)response;
if([ne statusCode] == 200) {
NSLog(@"connection state is 200 - all okay");
} else {
NSLog(@"connection state is NOT 200");
}
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"Conn Err: %@", [error localizedDescription]);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"Conn finished loading");
NSString *html = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
NSLog(@"OUTPUT:: %@", html);
}
Upvotes: 7
Reputation: 12081
Have you tried to implement the error delegate method?
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// do something with error
}
It can happen that you don't have an internet connection, or something else is wrong before NSURLConnection
is able to establish a connection. In this case you will not receive a http response or any other data. The error will provide more information.
[edit]
I just noticed the URL in the example code doesn't contain a host name. If this is the exact code you are using make sure you send the request to a correct URL.
// Replace
[NSURL URLWithString:@"myDomain/form.php"]
// with a correct url like
[NSURL URLWithString:@"http://mydomain.com/form.php"];
An error delegate method will actually provide you with an error that complains about a wrong URL.
Upvotes: 2