2

I am making an jsonstring. When i execute it, it works when i do it in my browser. I do this by logging the exact url and copy it in the browser. Than i get the HTTP Get that i want, but in the iPhone i only get a Bad Login.

- (IBAction)getDown:(id)sender { //perform get request
    NSLog(@"beginnen met versturen");

    //NSString * _barCode = [[NSUserDefaults standardUserDefaults] objectForKey:@"phoneNumber"];

    //build up the request that is to be sent to the server
    //NSString*jsonString = [[NSString alloc] initWithFormat:@"{\"barcode\":\"%@\"}", _barCode];


    NSString*jsonString = [[NSString alloc] initWithFormat:@"{\"barcode\":\"123456\"}"];

    NSString *str = [NSString stringWithFormat: @"http://server.nl/scan.php?data=%@",jsonString];
    NSLog(@"%@", str);
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL    URLWithString:str]];
    NSLog(@"url: %@", request);

    [request setHTTPMethod:@"GET"];
   // [request addValue:@"getValues" forHTTPHeaderField:@"METHOD"]; //selects what task the server will perform
    NSLog(@"met value: %@", request);

    //initialize an NSURLConnection  with the request
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if(!connection){
        NSLog(@"Connection Failed");
    }

}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{ // executed when the connection receives data

    receivedData = data;
    /* NOTE: if you are working with large data , it may be better to set recievedData as NSMutableData
     and use  [receivedData append:Data] here, in this event you should also set recievedData to nil
     when you are done working with it or any new data received could end up just appending to the
     last message received*/
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{ //executed when the connection fails

    NSLog(@"Connection failed with error: %@",error.localizedDescription);
}
-(void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{

    /*This message is sent when there is an authentication challenge ,our server does not have this requirement so we do not need to handle that here*/
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{

    NSLog(@"Request Complete,recieved %d bytes of data",receivedData.length);

    //[self.delegate requestReturnedData:receivedData];//send the data to the delegate
    NSData *data = receivedData;
    NSDictionary *dictionary = [NSDictionary dictionaryWithJSONData:data];
    NSLog(@"%@",dictionary.JSONString ); ; // set the textview to the raw string value of the data recieved

    NSString *value1 = [dictionary objectForKey:@"barcode"];
    NSLog(@"%@", value1);
    NSString *value2 = [dictionary objectForKey:@"product"];
    NSLog(@"%@",dictionary);
    NSLog(@"%@", value2);

}

Here's the log:

2013-01-10 16:31:46.550 Scanner[14875:907] http://server.nl/scan.php?data={"barcode":"123456"}
2013-01-10 16:31:46.551 Scanner[14875:907] url: <NSMutableURLRequest (null)>
2013-01-10 16:31:46.553 Scanner[14875:907] met value: <NSMutableURLRequest (null)>
**2013-01-10 16:31:46.556 Scanner[14875:907] Connection failed with error: bad URL**

When i delete the complete json from the string i get no bad url. So there might be the problem. Anyone know what i am doing wrong?

David Raijmakers
  • 1,369
  • 1
  • 16
  • 40

2 Answers2

3

You need to encode it, before perfoming an URL request. Best and most elegant solution would be adding a category over NSString for example, something like this:

- (NSString*)URLEncode {
    // Should not be encoded:-_.
    return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR(";/?:@&=+$,!*'()<>#%\"{}|\\^[]`~"), kCFStringEncodingUTF8) autorelease];
//
}

And when you make the request:

NSString *str = [NSString stringWithFormat: @"http://server.nl/scan.php?data=%@",jsonString];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL    URLWithString:[str URLEncode]];

If you don't want to use additional files (even thought that would be recommended), add this method to your class:

- (NSString*)URLEncode:(NSString )yourURL {
 // Should not be encoded:-_. 
return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR(";/?:@&=+$,!'()<>#%\"{}|\\^[]`~"), kCFStringEncodingUTF8) autorelease]; 
} 

and use

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:[self URLEncode:str]]; 
Vlad
  • 3,346
  • 2
  • 27
  • 39
  • NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:[str URLEncode]]]; – David Raijmakers Jan 10 '13 at 15:50
  • you need to include the headers for the cathegory you created. – Vlad Jan 10 '13 at 15:53
  • Wait what? Could you explain that to me? – David Raijmakers Jan 10 '13 at 15:54
  • Of even easier, just do an instance method in your class, something like this - (NSString*)URLEncode:(NSString *)yourURL { // Should not be encoded:-_. return [(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR(";/?:@&=+$,!*'()<>#%\"{}|\\^[]`~"), kCFStringEncodingUTF8) autorelease]; } and use NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:[self URLEncode:str]]; This is if you dont want additional files to your project. However, i recommend using the method i posted in my response. – Vlad Jan 10 '13 at 15:55
  • Could you please edit it in the answer? i cant see it like this – David Raijmakers Jan 10 '13 at 15:59
  • So, from XCode, File / new File / Cocoa Touch / Objective C cathegory. Name it whatever you want, and select cathegory on NSString from the dropdown menu. Then write the method in my response as you would in a normal class. Then from the class where you got your URL connection, #include "HowyouNamedYourCathegory.h", and you can use the method you declared in the cathegory on every NSString. Be sure to add in the cathegory files, both the definition in the .h and the implemetation in .m. Editing my response as well. Done, choose any of the methods you like. – Vlad Jan 10 '13 at 16:01
  • And while you're at it, take a look over this, if will be extremely helpfull for the future, especially for code reuse http://mobiledevelopertips.com/objective-c/categories.html – Vlad Jan 10 '13 at 16:24
1

I don't have much information right now, I apologize, I'm in a bit of a hurry and just saw your question. But I saw your question and I remember working on a project which was essentially an HTML-based remote control for the iphone, and when the user clicked on some of the buttons for the remote, it followed the urls that opened up identical pages but had server-side code to instruct the server to pause, play, stop, etc... I DO remember that the iPhone had a bug that caused it to not be able to parse all of my URLs, even though they were correctly formatted and worked on a desktop client. That is why I switched over to POST requests (where user clicks instead activated javascript functions that set hidden form variables and then submitted forms rather than directly navigating to long URLS). Anyways, I know this may not directly apply to you, but the point is that I did find a bug in the iPhone's URL parsing, so it might not be your fault. I'll look up any new information I can find a little later. Good luck.

John Davis
  • 736
  • 6
  • 14