从Cocoa发送POST表单

0 macos cocoa

大家好!我从http://deusty.blogspot.com/2006/11/sending-http-get-and-post-from-cocoa.html上读到了一篇文章,但我没有得到一些东西.我尝试用它来建立NSURLConnection,以及它根本不会接收数据?如果您对此感兴趣,请访问www.lockerz.com.

http://pastebin.com/8fP9TX8q.修复链接,因为我不能发布超过1.

它实际上说连接失败了,我不知道为什么......

Dav*_*ong 7

问题#1

在前两行中,立刻让我感到错误的是:

NSString *post = @"email-email=test@email.com&password-password=testpassword";
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
Run Code Online (Sandbox Code Playgroud)

提交POST表单(以及URL中的GET参数)时,只应对键和值进行URL编码.在这里,您不仅要对键和值进行编码,还要对=和进行编码&,这是完全错误的.我通常做这样的事情:

NSMutableDictionary * parameters = [NSMutableDictionary dictionary];
[parameters setObject:@"test@email.com" forKey:@"email-email"];
[parameters setObject:@"testpassword" forKey:@"password-password"];

NSMutableArray * encodedParameters = [NSMutableArray array];
for (NSString * key in parameters) {
  NSString * value = [parameters objectForKey:key];
  NSString * encoded = [NSString stringWithFormat:@"%@=%@", [key stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding], [value stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
  [encodedParameters addObject:encoded];
}

NSString * post = [encodedParameters componentsJoinedByString:@"&"];
NSData * postData = [post dataUsingEncoding:NSASCIIStringEncoding];
Run Code Online (Sandbox Code Playgroud)

您也可能遇到问题stringByAddingPercentEscapesUsingEncoding:.我NSString这里写了一个如何对字符串进行URL编码的类别.

问题#2

你永远不会等待连接发送. NSURLConnection,就像你使用它一样,是一个异步 API.因此,以下将失败:

NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (theConnection) {
  NSLog(@"Connection succeeded!");
}
Run Code Online (Sandbox Code Playgroud)

您正在测试的是没有成功完成连接,而是成功实例化连接对象.这是一个非常不同的事情.连接本身实际上可能无法完成运行循环的几次旋转.如果您希望连接是同步的(即,在执行下一行代码之前完成连接),那么您需要使用NSURLConnection同步API.

问题#3

这些行充满了失败:

receivedData = [[NSMutableData data] retain];
NSString *text = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
Run Code Online (Sandbox Code Playgroud)

[NSMutableData data]返回一个空数据对象. 它什么都没有.因此,如果您创建一个空数据对象,然后从数据中创建一个字符串,那么(惊喜)您将得到一个空字符串.

另外,你正在泄漏数据对象(因为你retain[这是不必要的],但从来没有release).

编辑,因为我感觉很慷慨......

以下工作正常(虽然我只是硬编码HTTPBody字符串而不是按照上面的建议构建它):

NSURL * url = [NSURL URLWithString:@"http://www.lockerz.com/auth/login/"];
NSMutableURLRequest * r = [[NSMutableURLRequest alloc] initWithURL:url];
[r setHTTPMethod:@"POST"];
[r setHTTPBody:[@"email%2Demail=test%40email%2Ecom&password%2Dpassword=testpassword" dataUsingEncoding:NSASCIIStringEncoding]];
[r setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

NSHTTPURLResponse * response = nil;
NSError * error = nil;
NSData * responseData = [NSURLConnection sendSynchronousRequest:r returningResponse:&response error:&error];
NSString * responseString = [[[NSString alloc] initWithData:responseData encoding:NSASCIIStringEncoding] autorelease];
NSLog(@"%@", responseString);
[r release];
Run Code Online (Sandbox Code Playgroud)

这正确执行,并responseString记录一些描述错误页面的HTML.但是,这并不令人惊讶,因为URL本身(http://www.lockerz.com/auth/login)在尝试使用原始问题中提供的凭据时会产生错误.