ios NSURLRequest : 发布数据并读取发布的页面

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10300353/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 18:02:28  来源:igfitidea点击:

NSURLRequest : Post data and read the posted page

iphoneobjective-ciosrequestnsurlrequest

提问by Agent 404

In iOS (current target 5.0, Base SDK 5.1) how can I send a post request to a server, and then read the contents of the page. For example, the page takes a username and password, and then echos true or false. This is just for a better understanding of NSURLRequest.

在 iOS(当前目标 5.0,Base SDK 5.1)中,如何向服务器发送 post 请求,然后读取页面内容。例如,页面采用用户名和密码,然后回显 true 或 false。这只是为了更好地理解 NSURLRequest。

Thanks in Advance!

提前致谢!

回答by Matt Melton

A few things first

先说几件事

  • Decide how you want to encode your data - JSON or url-encoding are a good start.
  • Decide upon a return value - will it be 1, TRUE or 0, FALSE, or even YES/non-nil nothing/nil.
  • Read up on the URL Loading System, it's your friend.
  • 决定如何编码数据 - JSON 或 url-encoding 是一个好的开始。
  • 决定一个返回值——它是 1、TRUE 还是 0、FALSE,或者甚至是 YES/non-nil 什么都没有/nil。
  • 阅读URL 加载系统,这是您的朋友。

Aim to make all your url connections asynchronous so your UI remains responsive. You can do this with NSURLConnectionDelegate callbacks. NSURLConnection has a small drawback: your code must be decoupled. Any variables you want available in the delegate functions will need to be saved to ivars or in your request's userInfo dict.

旨在使您的所有 url 连接异步,以便您的 UI 保持响应。您可以使用 NSURLConnectionDelegate 回调来做到这一点。NSURLConnection 有一个小缺点:你的代码必须是解耦的。您希望在委托函数中可用的任何变量都需要保存到 ivars 或您请求的 userInfo 字典中。

Alternatively you can use GCD, which, when coupled with the __block qualifiers, allows you to specify error/return code at the point you declare it - useful for one off fetches.

或者,您可以使用 GCD,当与 __block 限定符结合使用时,允许您在声明时指定错误/返回代码 - 对于一次性提取很有用。

Without further ado, here's a quick and dirty url-encoder:

事不宜迟,这是一个快速而肮脏的 url-encoder:

- (NSData*)encodeDictionary:(NSDictionary*)dictionary {
      NSMutableArray *parts = [[NSMutableArray alloc] init];
      for (NSString *key in dictionary) {
        NSString *encodedValue = [[dictionary objectForKey:key] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSString *encodedKey = [key stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
        NSString *part = [NSString stringWithFormat: @"%@=%@", encodedKey, encodedValue];
        [parts addObject:part];
      }
      NSString *encodedDictionary = [parts componentsJoinedByString:@"&"];
      return [encodedDictionary dataUsingEncoding:NSUTF8StringEncoding];
    }

Using a JSON library like JSONKitmakes encoding things easier, consider it!

使用像JSONKit这样的 JSON 库可以让编码变得更容易,考虑一下!

Method 1 - NSURLConnectionDelegate async callbacks:

方法 1 - NSURLConnectionDelegate 异步回调:

// .h
@interface ViewController : UIViewController<NSURLConnectionDelegate>
@end

// .m
@interface ViewController () {
  NSMutableData *receivedData_;
}
@end

...

- (IBAction)asyncButtonPushed:(id)sender {
  NSURL *url = [NSURL URLWithString:@"http://localhost/"];
  NSDictionary *postDict = [NSDictionary dictionaryWithObjectsAndKeys:@"user", @"username", 
                            @"password", @"password", nil];
  NSData *postData = [self encodeDictionary:postDict];

  // Create the request
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  [request setHTTPMethod:@"POST"];
  [request setValue:[NSString stringWithFormat:@"%d", postData.length] forHTTPHeaderField:@"Content-Length"];
  [request setValue:@"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:@"Content-Type"];
  [request setHTTPBody:postData];

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

  [connection start];  
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
  [receivedData_ setLength:0];
}

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

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
  NSLog(@"Succeeded! Received %d bytes of data", [receivedData_ length]);
  NSString *responeString = [[NSString alloc] initWithData:receivedData_
                                                  encoding:NSUTF8StringEncoding];
  // Assume lowercase 
  if ([responeString isEqualToString:@"true"]) {
    // Deal with true
    return;
  }    
  // Deal with an error
}

Method 2 - Grand Central Dispatch async function:

方法 2 - Grand Central Dispatch 异步函数:

// .m
- (IBAction)dispatchButtonPushed:(id)sender {

  NSURL *url = [NSURL URLWithString:@"http://www.apple.com/"];
  NSDictionary *postDict = [NSDictionary dictionaryWithObjectsAndKeys:@"user", @"username", 
                            @"password", @"password", nil];
  NSData *postData = [self encodeDictionary:postDict];

  // Create the request
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
  [request setHTTPMethod:@"POST"];
  [request setValue:[NSString stringWithFormat:@"%d", postData.length] forHTTPHeaderField:@"Content-Length"];
  [request setValue:@"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:@"Content-Type"];
  [request setHTTPBody:postData];

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // Peform the request
    NSURLResponse *response;
    NSError *error = nil;
    NSData *receivedData = [NSURLConnection sendSynchronousRequest:request  
                                           returningResponse:&response
                                                       error:&error];    
    if (error) {
      // Deal with your error
      if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
        NSLog(@"HTTP Error: %d %@", httpResponse.statusCode, error);
        return;
      }
      NSLog(@"Error %@", error);
      return;
    }

    NSString *responeString = [[NSString alloc] initWithData:receivedData
                                                    encoding:NSUTF8StringEncoding];
    // Assume lowercase 
    if ([responeString isEqualToString:@"true"]) {
      // Deal with true
      return;
    }    
    // Deal with an error

    // When dealing with UI updates, they must be run on the main queue, ie:
    //      dispatch_async(dispatch_get_main_queue(), ^(void){
    //      
    //      });
  }); 
}

Method 3 - Use an NSURLConnection convenience function

方法 3 - 使用 NSURLConnection 便利功能

+ (void)sendAsynchronousRequest:(NSURLRequest *)request queue:(NSOperationQueue *)queue completionHandler:(void (^)(NSURLResponse*, NSData*, NSError*))handler

Hope this helps.

希望这可以帮助。

回答by Kai Huppmann

  NSData *postData = [someStringToPost dataUsingEncoding:NSUTF8StringEncoding];

  NSURL *url = [NSURL URLWithString:someURLString];
  NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url];
  [req setHTTPMethod:@"POST"];
  [req setValue:[NSString stringWithFormat:@"%d", postData.length] forHTTPHeaderField:@"Content-Length"];
  [req setValue:@"application/x-www-form-urlencoded charset=utf-8" forHTTPHeaderField:@"Content-Type"];
  [req setHTTPBody:postData];

  NSError *err = nil;
  NSHTTPURLResponse *res = nil;
  NSData *retData = [NSURLConnection sendSynchronousRequest:req returningResponse:&res error:&err];
  if (err)
  {
    //handle error
  }
  else
  {
    //handle response and returning data
  }

回答by VIP-DEV

This project might be quite handy for your purpose. It will take care of your downloads and store it locally. Check out the link https://github.com/amitgowda/AGInternetHandler

这个项目可能是你的目的很方便。它将处理您的下载并将其存储在本地。查看链接https://github.com/amitgowda/AGInternetHandler