How to leave a set number of spaces in NSString? - objective-c

I have separate text objects for the unchanging portion (i.e. "Bonus Score: (+7%)") and the changing portion (e.g. "247,890"). Since they're separate, I want to leave space in the unchanging portion to display the number.
What I first tried was:
NSString* numberString = #"247,890";
NSString* blankScore = [#"" stringByPaddingToLength:[numberString length] withString: #" " startingAtIndex:0];
NSString* baseDisplay = [NSString stringWithFormat:#"BONUS SCORE: %# (+7%%)", blankScore];
'blankScore' was the correct length, but the resulting baseDisplay seemed to trim the spaces around where blankScore would be, making it too small of a space for the displayed number.
Next I tried another way of creating blankScore:
NSString* blankScore = [numberString stringByReplacingCharactersInRange:NSMakeRange(0, [numberString length]) withString:#" "];
But this returned a blankScore of length 1.
Am I understanding these NSString methods incorrectly? I checked the docs, and it seems like my understanding of these methods aligns with what's written there, but I still don't understand why I can't get my baseDisplay to have the correct number of spaces.

Have you printed blankScore on the console using NSLog? Actually your string is correct, but the output is trimmed at end of lines - this is why you see it as described.

#H2CO3 is on to the right solution. You should be using:
NSString *baseDisplay = [NSString stringWithFormat:#"BONUS SCORE: %# (+7%%)", numberString];
To make this work even better, you may want to consider an NSNumberFormatter to correctly format the changing part before inserting it into the baseDisplay object. Something like this:
NSNumber *changingNumber = [NSNumber numberWithDouble:247890];
NSNumberFormatter *correctFormat = [[NSNumberFormatter alloc] init];
[correctFormat setNumberStyle:NSNumberFormatterDecimalStyle];
[correctFormat setHasThousandSeparators:YES];
[correctFormat setUsesGroupingSeparator:YES];
NSString *numberString = [correctFormat stringFromNumber:changingNumber];
NSString *baseDisplay = [NSString stringWithFormat:#"BONUS SCORE: %# (+7%%)", numberString];
This way no matter what number you throw at it, it will correctly display "1,234,456" or "34,567", whatever.
EDIT:
Based on the comments to my answer you will need to use:
stringByPaddingToLength:withString:startingAtIndex:
It should look something like this:
NSString *templateString = #"BONUS SCORE:";
NSString *templateString2 = #"(+7%%)";
NSUInteger baseStringLength = [templateString length] + [numberString length];
NSString *spacedString = [templateString stringByPaddingToLength:baseStringLength withString:#" " startingAtIndex:0];
NSString *baseDisplay = [NSString stringWithFormat:#"%#%#", spacedString, templateString2];

Related

Scan string, get info. Xcode

I have made an app which the user types in data and it gets a url from google maps like this - [https://www.google.com.au/maps/search/nearest+pizza+shop/#-27.4823545,153.0297855,12z/data=!3m1!4b1
In the middle you see 27.4823545,153.0297855 this is long and lat. So with this I can make my maps work. But I really need to know how to scan this string (the url was made into a string) and get only those numbers, I have already tried this ->
NSString *currentURL = web.request.URL.absoluteString;
string1 = currentURL;
NSScanner *scanner = [NSScanner scannerWithString:string1];
NSString *token = nil;
[scanner scanUpToString:#"#" intoString:NULL];
[scanner scanUpToString:#"z" intoString:&token];
label.text = token;
I think it would be highly likely I did a mistake, since I am new to objective-c, but if there are more effective ways please share . :)
Thanks for all the people who took the time to help.
Bye All!
A solution:
Extrating the path from an NSURL. Then looking at each path components to extract the coordinates components :
NSURL *url = [NSURL URLWithString:#"https://www.google.com.au/maps/search/nearest+pizza+shop/#-27.4823545,153.0297855,12z/data=!3m1!4b1"];
NSArray *components = [url.path componentsSeparatedByString:#"/"];
NSArray *results = nil;
for (NSString *comp in components) {
if ([comp length] > 1 && [comp hasPrefix:#"#"]) {
NSString *resultString = [comp substringFromIndex:1]; // removing the '#'
results = [resultString componentsSeparatedByString:#","]; // lat, lon, zoom
break;
}
}
NSLog(#"results: %#", results);
Will print:
results: (
"-27.4823545",
"153.0297855",
12z
)
This solution gives you a lot of control points for data validation.
Hope this helps.
Edit:
To get rid of the "z". I would treat that as a special number with a number formatter in decimal style and specify that character as the positive and negative suffix:
NSString *targetStr = #"12z";
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.numberStyle = NSNumberFormatterDecimalStyle;
formatter.positiveSuffix = #"z";
formatter.negativeSuffix = #"z";
NSNumber *result = [formatter numberFromString:targetStr];
The var result will contain whatever positive or negative number before the 'z'. You could use a NSScanner to do the trick but I believe it's less flexible.
As a side note, it would be great to get that "z" (zoom's character) from Google's API. If they ever change it to something else your number will still be parsed properly.

Check if it is possible to break a string into chunks?

I have this code who chunks a string existing inside a NSString into a NSMutableArray:
NSString *string = #"one/two/tree";
NSMutableArray *parts = [[string componentsSeparatedByString:#"/"] mutableCopy];
NSLog(#"%#-%#-%#",parts[0],parts[1],parts[2]);
This command works perfectly but if the NSString is not obeying this pattern (not have the symbol '/' within the string), the app will crash.
How can I check if it is possible to break the NSString, preventing the app does not crash?
Just check parts.count if you don't have / in your string (or only one), you won't get three elements.
NSString *string = #"one/two/tree";
NSMutableArray *parts = [[string componentsSeparatedByString:#"/"] mutableCopy];
if(parts.count >= 3) {
NSLog(#"%#-%#-%#",parts[0],parts[1],parts[2]);
}
else {
NSLog(#"Not found");
}
From the docs:
If list has no separators—for example, "Karin"—the array contains the string itself, in this case { #"Karin" }.
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/occ/instm/NSString/componentsSeparatedByString:
You might be better off using the "opposite" function to put it back together...
NSString *string = #"one/two/three";
NSArray *parts = [string componentsSeparatedByString:#"/"];
NSString *newString = [parts componentsJoinedByString:#"-"];
// newString = #"one-two-three"
This will take the original string. Split it apart and then put it back together no matter how many parts there are.

Xcode - build string from multiple sources

Hi just starting to learn this language, more of a javascript/PHP guy...
I can't seem to figure out the proper syntax and after searching the internets for a straight answer or explanation I decided to bother you SOF community:
This works as I want it to work:
self.displaysTheStack.text = [self.displaysTheStack.text stringByAppendingString:#" "];
self.displaysTheStack.text = [self.displaysTheStack.text stringByAppendingString:operation];
self.displaysTheStack.text = [self.displaysTheStack.text stringByAppendingString:#" "];
I wanted to know if I could do the same thing in less lines something like:
NSString *displayTheArrayText = [NSString stringWithFormat:#" ",operation,#" "];
self.displaysTheStack.text = [self.displaysTheStack.text stringByAppendingString:displayTheArrayText];
When I do it this way I get the Two #" " (spaces) but "operation" doesn't show up: why and how do I write the latter command properly?
stringWithFormat: uses C-style formats similar to those used by printf
you probably want something like that:
NSString *displayTheArrayText = [NSString stringWithFormat:#" %# ",operation];
have a look at Formatting String Objects
self.displaysTheStack.text = [NSString stringWithFormat:#"%# %# ", self.displaysTheStack.text, operation];
Alternately:
NSMutableString *string = [NSMutableString stringWithString:self.displaysTheStack.text];
[string appendFormat:#" %# ", operation];
self.displaysTheStack.text = string;

NSString "Expected ':' before ']' token" error

My method aims to extract information on a game level from an input string. The input specifies the size of the 2D array playing area, as well as what items are present at what points in the 2D array.
For example, "4,3 . a,b,c . d,e,f . g,h,i . j,k,l" would comprise 4 columns and 3 rows, to look like this (without the hyphens):
a---d---g---j
b---e---h---k
c---f---i---l
The code works fine until the last line, where I get the error:
"Expected ':' before ']' token".
I've been trying to solve this for a while, so I'll be quite embarrassed if it's something stupid I've missed! Any help would be much appreciated.
-(void)readLevelDataFromString:(NSString*)inputString {
//remove spaces from the input
NSString *tempString = [inputString stringByReplacingOccurrencesOfString:#" " withString:#""];
//make mutable
NSMutableString *levelDataString = [NSMutableString stringWithString:tempString];
//trim first 4 characters, which we don't need
[levelDataString deleteCharactersInRange:NSMakeRange(0, 4)];
//separate whole string into an array of strings, each of which contains information on the particular column
NSArray *levelDataStringColumns = [levelDataString componentsSeparatedByString:#"."];
NSAssert([levelDataStringColumns count] == numColumns, #"In the level data string, the number of columns specified did not match the number of X tiles present.");
NSString *columnString = [[NSString alloc] initWithString:[[levelDataStringColumns] objectAtIndex:0]];
}
You have an extra set of []. You want:
NSString *columnString = [[NSString alloc] initWithString:[levelDataStringColumns objectAtIndex:0]];
You have an extra bracket on the last line, change it to this:
NSString *columnString = [[NSString alloc] initWithString:[levelDataStringColumns objectAtIndex:0]];
Try this for the last line:
NSString *columnString = [[NSString alloc] initWithString:[levelDataStringColumns objectAtIndex:0]];

Merge 5 NSStrings in Objective-C

I have multiple NSStrings and i wish to merge them into one other, here is my code so far...
NSString *newURL = [_parameters objectForKey:#"url"];
NSString *emailBody = #"Hey!<br>I just snipped my long url with My Cool App for iPhone in just a few seconds!<p><b>"+newURL+#"</b></p>";
If you know the number of your existing strings, you can just concat them:
NSString* longString = [firstString stringByAppendingString:secondString];
or:
NSString* longString = [NSString stringWithFormat:#"A string: %#, a float: %1.2f", #"string", 31415.9265];
If you have an arbitrary number of strings, you could put them in an NSArray and join them with:
NSArray* chunks = ... get an array, say by splitting it;
NSString* string = [chunks componentsJoinedByString: #" :-) "];
(Taken from http://borkware.com/quickies/one?topic=NSString)
Another good resource for string handling in Cocoa is: "String Programming Guide"
You can try
NSString *emailBody = [ NSString stringWithFormat: #"Hey!<br>I just snipped my long url with Snippety Snip for iPhone in just a few seconds, why not check it out?<p><b>%#</b></p>", newURL ];
Given that you've got multiple strings I recommend using an Array:
NSArray *array = [NSArray arrayWithObjects:#"URL", #"person", "body"];
NSString *combined = [array componentsJoinedByString:#""];
Formatting string has better readability and less error-prone:
NSString *newURL = [_parameters objectForKey:#"url"];
NSString *emailBody = [NSString stringWithFormat:#"Hey!<br>I just snipped my long url with Snippety Snip for iPhone in just a few seconds, why not check it out?<p><b>%#</b></p>", newUrl, newUrl];
You can concatenate strings in Cocoa using:
[NSString stringByAppendingString:]
Or you could use the [NSString stringWithFormat] method which will allow you to specify a C-style format string with a variable argument list to populate the escape sequences.