1

I am trying to post and JSON data to server. My JSON is: { “username”:”sample”, “password” : “password-1” }

The way I am sending it to server is:

NSError *error;

NSString *data = [NSString stringWithFormat:@"{\"username\":\"%@\",\"password\":\"%@\"}",_textFieldUserName.text,_textFieldPasssword.text];
NSData *postData = [data dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSData *jsonData = [NSJSONSerialization JSONObjectWithData:postData options:0 error:&error];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:@"My URL"]];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:jsonData];

NSURLResponse *requestResponse;
NSData *requestHandler = [NSURLConnection sendSynchronousRequest:request returningResponse:&requestResponse error:nil];

NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:requestHandler options:0 error:&error];
NSLog(@"resposne dicionary is %@",responseDictionary);

NSString *requestReply = [[NSString alloc] initWithBytes:[requestHandler bytes] length:[requestHandler length] encoding:NSASCIIStringEncoding];
NSLog(@"requestReply: %@", requestReply);

The JsonData that is created is a valid JSON accepted by the server. But the app is crashing and the error is:

-[__NSCFDictionary length]: unrecognized selector sent to instance 0x1702654c0

what is wrong that i am doing here?

  • Which line is the crash occurring on? See http://stackoverflow.com/a/10830845/123632 for setting an exception breakpoint. – Ashley Mills May 07 '15 at 10:34
  • Application is crashing at: NSData *requestHandler = [NSURLConnection sendSynchronousRequest:request returningResponse:&requestResponse error:nil]; – praneti patidar May 07 '15 at 10:44

3 Answers3

3

I always use this method in my apps to perform API calls. This is the post method. It is asynchronous so you can specify a callback to be called when the server answer.

-(void)placePostRequestWithURL:(NSString *)action withData:(NSDictionary *)dataToSend withHandler:(void (^)(NSURLResponse *response, NSData *data, NSError *error))ourBlock {
    NSString *urlString = [NSString stringWithFormat:@"%@", action];
    NSLog(@"%@", urlString);

    NSURL *url = [NSURL URLWithString:urlString];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    NSError *error;

    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dataToSend options:0 error:&error];

    NSString *jsonString;
    if (! jsonData) {
        NSLog(@"Got an error: %@", error);
    } else {
        jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

        NSData *requestData = [NSData dataWithBytes:[jsonString UTF8String] length:[jsonString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];

        [request setHTTPMethod:@"POST"];
        [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [request setValue:@"application/json; charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
        [request setValue:[NSString stringWithFormat:@"%lu", (unsigned long)[requestData length]] forHTTPHeaderField:@"Content-Length"];
        [request setHTTPBody: requestData];

        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:ourBlock];
    }
}

You can easily call it:

- (void) login:(NSDictionary *)data
                    calledBy:(id)calledBy
                 withSuccess:(SEL)successCallback
                  andFailure:(SEL)failureCallback{
    [self placePostRequestWithURL:@"yourActionUrl"
                  withData:data
               withHandler:^(NSURLResponse *response, NSData *rawData, NSError *error) {
                   NSString *string = [[NSString alloc] initWithData:rawData
                                                            encoding:NSUTF8StringEncoding];

                   NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
                   NSInteger code = [httpResponse statusCode];
                   NSLog(@"%ld", (long)code);

                   if (!(code >= 200 && code < 300)) {
                       NSLog(@"ERROR (%ld): %@", (long)code, string);
                       [calledBy performSelector:failureCallback withObject:string];
                   } else {
                       NSLog(@"OK");

                       NSDictionary *result = [NSDictionary dictionaryWithObjectsAndKeys:
                                               string, @"id",
                                               nil];
                       [calledBy performSelector:successCallback withObject:result];
                   }
               }];
}

And finally, you invocation:

NSDictionary *dataToSend = [NSDictionary dictionaryWithObjectsAndKeys:
_textFieldUserName.text, @"username", 
_textFieldPasssword.text, @"password", nil];

[self login:dataToSend 
    calledBy:self 
    withSuccess:@selector(loginDidEnd:) 
    andFailure:@selector(loginFailure:)];

Don't forget to define your callbacks:

- (void)loginDidEnd:(id)result{
    NSLog(@"loginDidEnd:");
    // Do your actions
}

- (void)loginFailure:(id)result{
    NSLog(@"loginFailure:");
    // Do your actions
}
EnriMR
  • 3,924
  • 5
  • 39
  • 59
1

First you create an NSString* that is supposed to contain JSON data. This doesn't work in general if the username and password contain any unusual characters. For example, I make sure that I have a quotation mark in my password to make sure that stupid software crashes.

You turn that string into an NSData* using ASCII encoding. So if my username contains any characters that are not in the ASCII character set, what you get is nonsense.

You then use the parser to turn this into a dictionary or array, but store the result into an NSData. Chances are that the parse fails and you get nil, otherwise you get an NSDictionary* or an NSArray*, but most definitely not an NSData*.

Here's how you do it properly: You create a dictionary, and then turn it into NSData.

NSDictionary* dict = @{ @"username": _textFieldUserName.text, 
                        @"password": _textFieldPasssword.text };
NSError* error; 
NSData* data = [NSJSONSerialization dataWithJSONObject:dict options:0 error:&error];

That's it.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
0

try this:

     NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:@"My URL"];
        if (!request) NSLog(@"Error creating the URL Request");

        [request setHTTPMethod:@"POST"];
        [request setHTTPBody:[data dataUsingEncoding:NSUTF8StringEncoding]];
[request setValue:@"text/json" forHTTPHeaderField:@"Content-Type"];
        NSLog(@"will create connection");

        // Send a synchronous request
        NSURLResponse * response = nil;
        NSError * NSURLRequestError = nil;
        NSData * responseData = [NSURLConnection sendSynchronousRequest:request
                                              returningResponse:&response
                                               error:&NSURLRequestError];
Dev138
  • 334
  • 1
  • 13