3

Can someone please help me decipher this code? It's executing when a user pushed a button to submit the data, or in this case, a "question" in the iPhone app.

I know that it's sending the string to my phpscript.php hosted on the server, but what i'm not familiar with are the long list of commands happening.

NSUserDefaults *p = [NSUserDefaults standardUserDefaults];
[p setObject:[NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://website.com/phpscript.php?user=%@&pass=%@&cat=%@&sub=%@&body=%@",[[p valueForKey:@"user"] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],[[p valueForKey:@"pass"] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],sport,@"",[[tvQ.text stringByReplacingOccurrencesOfString:@"\n" withString:@" "] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]]]] forKey:@"q"];
walkytalky
  • 9,453
  • 2
  • 36
  • 44
BigMike
  • 1,103
  • 3
  • 22
  • 34
  • 11
    That is horrible. Whoever wrote that needs counselling. – Adam Eberbach Aug 10 '10 at 22:43
  • That code just goes to show why software should be written for humans to read. Yes it works, yes it's all on one line and doesn't have lots of one-shot variables but it's not maintainable. In these days of fast, optimising compilers it probably isn't even efficient. Whoever wrote that was just trying to prove what a hardcore programmer he/she was. – Abizern Aug 11 '10 at 00:51
  • 1
    My developer did that....the app was completed, and I took over. Now trying to figure things out and clean up. – BigMike Aug 11 '10 at 01:56
  • 3
    Wow... I'm surprised he didn't just put it all on one line, replacing `p` with `[NSUserDefaults standardUserDefaults]`. – dreamlax Aug 11 '10 at 02:47
  • 2
    @BigMike: So you took over because you fired your developer? – JeremyP Aug 11 '10 at 08:26
  • @jeremy - yes, that was the case – BigMike Sep 11 '10 at 16:17

2 Answers2

8

Breaking it down makes it a bit easier.

NSUserDefaults *p = [NSUserDefaults standardUserDefaults];
NSString* string1 = [[p valueForKey:@"user"] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString* string2 = [[p valueForKey:@"pass"] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString* string3 = [[tvQ.text stringByReplacingOccurrencesOfString:@"\n" withString:@" "] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString* urlString = [NSString stringWithFormat:@"http://website.com/phpscript.php?user=%@&pass=%@&cat=%@&sub=%@&body=%@",string1,string2,sport,@"",string3];
id val1 = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString]];
[p setObject:val1 forKey:@"q"];

So p is a dictionary object loaded from user defaults, looks like some login credentials that are probably saved from last time the app was run.

stringByAddingPercentEscapesUsingEncoding is a standard method that makes it safe to transmit characters like ' ' (space) or '%' in a request. It is applied to the strings to ensure the request will reach the server looking like it was intended.

String1 and String2 are the username and passwords presumably. String3 is the body of the query I guess.

When the URL is built it executes the query represented by urlString (the code will pause at this point while the fetch is executed - hopefully this whole block is already on a secondary thread). The result of the query is stored in dictionary p and can be accessed through a key @"q".

Handling ampersands explicitly:

[myString replaceOccurrencesOfString:@"&" withString:@"%26" options:NSCaseInsensitiveSearch range:wholeString];

This method can be applied to any string - if it is applied to the same string twice then the second time it will do nothing.

Adam Eberbach
  • 12,309
  • 6
  • 62
  • 114
  • Adam, this is awesome. Thank you. Is there anywhere in here I can have it accept the ampersand (&) so I can pass it to my php script? I see it's encoding other special characters. – BigMike Aug 10 '10 at 23:04
  • In http://stackoverflow.com/questions/705448/iphone-sdk-problem-with-ampersand-in-the-url-string, Roger Nolan gave a code example that will handle everything that stringByAddingPercentEscapesUsingEncoding doesn't. But if you just want '&' - you can use "%26". See the line of code added to the answer. – Adam Eberbach Aug 10 '10 at 23:08
  • Adam, sorry for not being up-to-speed, but if I wanted to cover all my bases, with the Roger Nolan example, where do I plug in the "NSMutableString *escaped" code example into the clean code you provided above? – BigMike Aug 10 '10 at 23:21
  • Let's say you have some ordinary text. Make it a NSString with something like NSString* myString = [NSString stringWithFormat:@"%s" myOrdinaryASCIITextString]. Then you can use the replaceOccurrencesOfString method as shown. Then the string is ready to send. You would probably have it as part of string3 in the example, or append it to string 3? – Adam Eberbach Aug 10 '10 at 23:25
  • Would it look something like NSString* string3 = [[tvQ.text stringByReplacingOccurrencesOfString:@"\n" withString:@" "] [[tvQ.text replaceOccurrencesOfString:@"&" withString:@"%26" options:NSCaseInsensitiveSearch range:wholeString] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; – BigMike Aug 10 '10 at 23:32
  • Adam - how can I have [[tvQ.text stringByReplacingOccurrencesOfString:@"&" withString:@"and"] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding] in the code twice. Seems to not be accepting it. – BigMike Aug 11 '10 at 01:48
  • Mike you need to nest them. NSString* myNewString = [[[myString operation1] operation2] operation3]; The important thing to know is that the output of these string methods is a string. – Adam Eberbach Aug 11 '10 at 02:04
3

It is creating a string from the tvQ.text that replaces any new lines with a blank space, it is then creating the url looking string using the above string and others it grabs (values in the user defaults, from the looks of things). it is then fixing percent escapes in this url string, and then creating a NSURL object from the NSString. This NSURL is then set as the object for the key "q" in the user defaults.

and it makes my head hurt.

Jesse Naugher
  • 9,780
  • 1
  • 41
  • 56
  • Yeah, my head was already hurting. Anyway to clean this up? I'm having an issue of an ampersand (&) not being passed to my php script, which then inserts into my database. The string gets cut off. For example, if I type "hello & goodbye" into the app, it ends up only passing "hello" to my script, which gets put into the database. – BigMike Aug 10 '10 at 23:00