Objective - C Rookie NSString Problem - iphone

I have this code:
// Fill out the email body text
NSString *emailBody = (#"Name:%#\nNumber of People:\nDate:", name.text);
NSLog(#"%#", emailBody);
As you can see I'm trying to append name.text to the e-mail body just after "Name:". However, NSLog only outputs the string contained in name.text and none of the rest of the e-mail body. What am I doing wrong here that the code deletes the rest of the string apart from name.text?
E.G if name.text contained the text "Jack", then NSLog would only output "Jack" and not:
Name: Jack
Number of People: x
Date: x
Which is what I am looking for.
Can anyone give me an insight as to what I'm doing wrong?
Thanks,
Jack

Use +stringWithFormat method:
NSString *emailBody = [NSString stringWithFormat:#"Name:%#\nNumber of People:\nDate:", name.text];
What you have now is a valid code, but it doesn't do what you want:
(#"Name:%#\nNumber of People:\nDate:", name.text);
calls a comma operator - it evaluates its 1st parameter, discards it and returns 2nd parameter, so that's why emailBody is eventually filled with name.text value

You should write
NSString *emailBody = [#"Name:%#\nNumber of People:\nDate:" stringByAppendingString:name.text];
Or, if it doesn't compile,
[[NSString stringWithString:#"Name:%#\nNumber of People:\nDate:"] stringByAppendingString:name.text]

generally you want to either use stringWithFormat as was suggested, which creates an autorelease string that follows the format you have, or you can use initWithFormat instead, which creates a string you can manually manage for better memory behavior, if necessary.
some books will insist that for the iphone, which has limited memory, you don't depend on autorelease objects more than it absolutely necessary, so you'd often find this instead:
NSString *emailBody = [[NSString alloc] initWithFormat:#"Name:%#\nNumber of People:\nDate:", name.text];
Then you can use "emailBody" and immediately after you are done with it, put in this line:
[emailBody release];
This is a good habit to get into in general.

Related

NSArray compontentsSeperatedByString returns unrecognized selector

I have a string containing three words, seperated by a pipeline ( | )
I want to break these up into three separate strings
NSArray *bits = [word.variants componentsSeparatedByString: #"|"];
NSLog(#"BITS: %#", bits);
This returns an unrecognized selector. I use this line of code in other areas in my project, and it works fine. But not on this one.
-[__NSArrayI componentsSeparatedByString:]: unrecognized selector sent to instance 0x6dbfa80
Any ideas?
I have also same problem while my string having so many white character , new line character so i cant do anything but finally i got solution as per following:
NSString *artwork = [currentURL valueForKey:#"artwork_large"];
//i got the string artwork ,which is fetch from json.
[smg addObject:artwork];
// add this string to 0th index of an array name:smg
NSSet *setObj1 = [NSSet setWithArray:smg];
//make the nsset for my array (named :smg)
NSString *pictureName = [[setObj1 allObjects] componentsJoinedByString:#","];
//make the string from all the sets joined by ","
picArray = [pictureName componentsSeparatedByString:#","];
//now its time for normal operation means makes the array (name: picArray) from string by componenet separatedbystring method
this way now i got the perfect array which is in our control
You didn't give us the whole error message, but my bet: You are overreleasing either word or variants and therefor the message is received by another object, that doesn't have the method mentioned in the selector. Try NSZombieEnbled. You will find enough post about it on StackOverflow.
edit
The error posted by you fits to my assumption. The only other explanation: variants is a NSArray.
Make it as following, assuming variants as NSString
NSString *lvariant = word.variants;
NSArray *bits = [lvariant componentsSeparatedByString: #"|"];

String manipulation in objective-c

this is hard to describe but I am currently catching a string from a database, this string can be 1-4 characters long, however I am wanting to always display 4 characters, so if i get say a string back that is 34, i want it to be 0034.
I have set up a method to catch the string so now I just need to figure out how to do this. what I then plan to do is feed that string into a NSArray so I can send each [i'th] of the array off to 4 differetn methods that control animations in my app.
The reason its in string format is because I have had to bounce it round from hex, to int to string for various formatting reasons within the application.
this is my code i have so far. Suggestions/solutions would be great thankyou, I am so new its hard to find solutions for stuff like string manipulation etc..
//... other method I am getting the string from/.
[self formatMyNumber:dataString];
///..
-(void)formatMyNumber:(NSString *)numberString{
//resultLabel.text = numberString; //check to make sure string makes it to here.
//NSLog(#"hello From formatMyNumber method"); //check
}
//..
//the with send off each character to 4 animation methods that accept integers.
- (void)playAnimationToNumber:(int)number{
//...
//UpDated... weird stuff happening.
here is my method so far.
//Number Formatter
-(void)formatMyNumber:(NSString *)numberString{
NSLog(#"This is what is passed into the method%#",numberString);
int tempInt = (int)numberString;
NSLog(#"This is after I cast the string to an int %i",tempInt);
//[NSString alloc] stringWithFormat:#"%04d", numberString];
NSString *tempString = [[NSString alloc] initWithFormat:#"%04d", tempInt];
NSLog(#"This is after I try to put zeros infront %#",tempString);
//resultLabel.text = tempString;
//NSLog(#"hello From formatMyNumber method");
}
this is the output.
[Session started at 2011-06-19
16:18:45 +1200.] 2011-06-19
16:18:54.615 nissanCode0.1[4298:207]
731 2011-06-19 16:18:54.616
nissanCode0.1[4298:207] 79043536
2011-06-19 16:18:54.617
nissanCode0.1[4298:207] 79043536
2011-06-19 16:18:54.617
nissanCode0.1[4298:207] hello From
formatMyNumber method
As far as the number of zeros preceding your string goes there are a couple of ways to do this. I'd suggest:
NSString *myString = [NSString stringWithFormat:#"%04d",[dataString intValue]];
Is it possible you could have the number in integer form instead of string form? If so, it's pretty easy to use [NSString stringWithFormat:#"%04d", number]. See here for a list of the possible format specifiers.
See what stringWithFormat: can do. I realize you mentioned your numbers are NSStrings, but if they were ints, or you convert them back to ints, the following may do the trick. Modify the following to best suit your need:
return [NSString stringWithFormat:#"%04d", number];

Trouble appendingStrings (NSString) within a for loop

Ok, so i'm pulling a list of addresses for a given postcode from an online datasource. The requests sends me a JSON of an array of arrays, within the first layer of the array are arrays of strings.
These contain for example.
Addressline1, Addressline2, Town, Country, Postcode
I need to add all of these strings together for each address, so that I have just 1 working string for each address. However, sometimes there is a blank field #"" within the arrays.
Here is my for loop.
id object;
NSString *startString = [NSString stringWithString:#"testStart:"];
for (object in arrayContainingAddress) {
NSString *useableString = [NSString stringWithFormat:#"%#", object];
if (![useableString isEqualToString:#""]) {
NSLog(#"%#", useableString);
[startString stringByAppendingString:useableString];
NSLog(#"%#", startString);
}
}
NSLog(#"%#", startString);
The problem is, startString is ALWAYS logging out at the end as 'testStart:', yet useableString logs to contain the correct addressline, town etc, The startString NSLog within the for loop also just logs out as 'testStart:'.
This entire chunk of code is sat inside a while loop which switches the 'arrayContainingAddress' for the appropriate array for each address.
The reason for the 'id object' is that my JSON conversion sometimes converts the values into NSNumbers (the first line of an address might be a house number, e.g. 123) and so I prevent a crash here.
TLDR: The string 'startString' is not being appended throughout my for loop.
stringByAppendingString doesn't do anything to the string it is called on. It returns a new autoreleased string that is the concatenation of the two.
What you want to do is make your startString a mutable string:
NSMutableString *startString = [NSMutableString stringWithString:#"testStart:"];
then use the appendString method:
[startString appendString:useableString];
You should change your code, as follows:
if (![useableString isEqualToString:#""]) {
NSLog(#"%#", useableString);
startString = [startString stringByAppendingString:useableString];
NSLog(#"%#", startString);
}
You were not updating the startString in the loop.

int to NSString issue

I use the following statement for into to NSString conversion (with a find/replace)
curr_rep_date = [tmpRptDt stringByReplacingOccurrencesOfString:tmpYrVal withString:[NSString stringWithFormat:(tmpCurrYearInt-1)]];
I have declared
int tmpYrVal;
NSMutableString *tmp_dt,*curr_rep_date;
But the program seems to be crashing and the debugger is not giving any hint.
Could someone help me with the issue and what would be the correct usage.
There's a number of problems here.
Firstly, sringByReplacingOcurrancesOfString:withString: is expecting NSStrings as parameters, not ints. That's the reason why it crashes. The method Is attempting to send a message to a primitive type, not an object.
Secondly, you need to use a proper format string for the stringWithFormat: method. This is the same as how NSLog works.
A format string can look like #"some text %d". It would then be followed by a comma separated list of values to be used in place of the % placeholders.
Example:
[NSString stringWithFormat:#"%d", myIntValue];
Will effectively turn your int into a string, as it creates a new string with a format using your int.
You invoked the stringWithFormat - Method without a format string. [NSString stringWithFormat: #"%i", (tmpCurrYearInt-1)] should solve your problem.
You are missing the format
curr_rep_date = [tmpRptDt stringByReplacingOccurrencesOfString:tmpYrVal withString:[NSString stringWithFormat:#"%d", (tmpCurrYearInt-1)]];
Basic int to NSString conversion works like this:
NSString* s = [NSString stringWithFormat:#"%d", intNumber];

Organize objective-C string for filters

How can I organize this string better for best coding practices. It's a string that defines filters:
NSString* string3 = [[[[[[tvA.text stringByReplacingOccurrencesOfString:#"\n" withString:#" "] stringByReplacingOccurrencesOfString:#"&" withString:#"and"] stringByReplacingOccurrencesOfString:#"garçon" withString:#"garcon"] stringByReplacingOccurrencesOfString:#"Garçon" withString:#"Garcon"] stringByReplacingOccurrencesOfString:#"+" withString:#"and"] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
Is there a way to have it be:
NSString* string3 = [[[[[tvA.text filter1] filter2] filter3] filter4] filter5] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
You shouldn't be replacing & and + before percent-escaping. The problem is that stringByAddingPercentEscapesUsingEncoding: (IIRC) adds the minimum escapes to make it a "valid" URL string, whereas you want to escape anything that might have a special interpretation. For this, use CFURLCreateStringByAddingPercentEscapes():
return [(NSString*)CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)aString, NULL, (CFStringRef)#":/?#[]#!$&'()*+,;=", kCFStringEncodingUTF8) autorelease];
This encodes & and + correctly, instead of just changing them to "and". It also encodes newlines as %0a (so you might want to replace them with spaces; that's your call), and encodes ç as %C3%A7 (which is decoded correctly if you use UTF-8 on the server).
The first thing I'd do is capture the transformation into a method somewhere (where "somewhere" is either an instance method on an appropriate object or a class method on a utility class).
- (NSString *) transformString: (NSString *) aString
{
NSString *transformedString;
transformedString = [aString stringByReplacingOccurrencesOfString:#"\n" withString:#" "];
transformedString = [transformedString stringByReplacingOccurrencesOfString:#"&" withString:#"and"];
transformedString = [transformedString stringByReplacingOccurrencesOfString:#"garçon" withString:#"garcon"];
transformedString = [transformedString stringByReplacingOccurrencesOfString:#"Garçon" withString:#"Garcon"];
transformedString = [transformedString stringByReplacingOccurrencesOfString:#"+" withString:#"and"];
transformedString = [transformedString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
return transformedString;
}
Then:
NSString *result = [myTransformer transformString: tVA.text];
A bit brutish, but it'll work. And by "brutish", I mean that it is going to be slow and will cause a bunch of interim strings to pile up in the autorelease pool. However, if this is something that you only do every now and then, don't worry about it -- while brutish, it is certainly quite straightforward.
If, however, this shows up in performance analysis as a bottleneck, you could first move to using NSMutableString as it has methods for doing replacements in place. That, at least, will reduce memory thrash and will likely be a bit faster in that there is less copying of strings going on.
If that is still too slow, then you will likely need to write yourself a fun little bit of parsing and processing code that walks through the original and copies it to new a new string while also doing any necessary transforms along the way.
But, don't bother optimizing until you prove that it is a problem. And, of course, if it is a problem, you have just one method to optimize!
If performance is not crucial, put the strings and their replacements into an NSDictionary and iterate over the items. Put it all in a helper method and use a NSMutableString to work on it (which reduces at least some of the cost).