Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
313 views
in Technique[技术] by (71.8m points)

iphone - NSURLRequest : Post data and read the posted page

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.

Thanks in Advance!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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.

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.

Without further ado, here's a quick and dirty 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 JSONKit makes encoding things easier, consider it!

Method 1 - NSURLConnectionDelegate async callbacks:

// .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:

// .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

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

Hope this helps.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...