Easiest way to format a number with thousand separators to an NSString according to the Locale - cocoa

I can't seem to find an easy way to do it. The exact thing I need is:
[NSString stringWithFormat:#"%d doodads", n];
Where n is an int. So for 1234 I'd want this string (under my locale):
#"1,234 doodads"
Thanks.

For 10.6 this works:
NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
NSString *numberString = [numberFormatter stringFromNumber: [NSNumber numberWithInteger: i]];
And it properly handles localization.

I have recently discovered this one-liner:
[#1234567 descriptionWithLocale:[NSLocale currentLocale]]; // 1,234,567
Or in Swift 2:
1234567.descriptionWithLocale(NSLocale.currentLocale()) // 1,234,567
Swift 3/4:
(1234567 as NSNumber).description(withLocale: Locale.current)
Formatted per the question:
[#(n) descriptionWithLocale:[NSLocale currentLocale]];
Formatted without Objective-C literals:
[[NSNumber numberWithInt:n] descriptionWithLocale:[NSLocale currentLocale]];
This is the solution I was looking for when I asked the question. Available since iOS 2.0 and OS X 10.0, documented to return a string version of the number formatted as per the locale provided. stringValue is even documented to use this method but passing nil.
Seeing as it is my question and this fits my answer best, I am tempted to change the tick, but it seems cruel. Update I changed the tick, this answer is the answer.

The below doesn't address the locale, but it is a better way (in my opinion) of setting the thousand separator on the number formatter.
NSNumberFormatter *numberFormat = [[[NSNumberFormatter alloc] init] autorelease];
numberFormat.usesGroupingSeparator = YES;
numberFormat.groupingSeparator = #",";
numberFormat.groupingSize = 3;

Todd Ransom answered this perfectly.
I would just like to add (in a separate comment, so I can show some nicely formatted code), that if you plan to do this regularly, it's worth creating an NSString helper class.
So, create yourself an NSStringHelper.h containing this:
#import <Foundation/Foundation.h>
#interface NSString (NSStringHelper)
+(NSString*)formatWithThousandSeparator:(NSInteger)number;
#end
..and an NSStringHelper.m file containing this:
#import "NSStringHelper.h"
#implementation NSString (NSStringHelper)
+(NSString*)formatWithThousandSeparator:(NSInteger)number
{
// Format a number with thousand seperators, eg: "12,345"
NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
NSString *result = [numberFormatter stringFromNumber:[NSNumber numberWithInteger:number]];
return result;
}
#end
This gives you the perfect way to reuse this code in future projects.
#import "NSStringHelper.h"
NSInteger numOfUsers = 12345;
NSString* strNumberOfUsers = [NSString formatWithThousandSeparator:numOfUsers];
Cool, hey ?
Again, apologies for reposting Todd's answer (which was exactly what I was looking for !), but this is a great way to solve the problem, and have it ready to be used in your future XCode projects.

Use an NSNumberFormatter.

Related

Setting UILabel to Same value as NSString

I have searched for hours on this one subject and still have not been able to solve my problem. I have a string value that I need converted into a label. In my code I save the NSString and then make sure I am getting a value with the NSLog (which I DO). Then is where I am having problems. I try to set the label value equal to the nesting but when I run its NSLog I get (null). So my question is how may I make my label equal the value of my string? Thank you so much!
NSString *linkString = self.product[#"link"];
NSLog(#"%#", linkString);
linkLabel.text = linkString;
NSLog(#"%#", linkLabel);
Your NSString will never be equal to your UILabel.
on the other hand, your UILabel's text property which is an NSString will be
try to change the code to this
NSString *linkString = self.product[#"link"];
NSLog(#"%#", linkString);
linkLabel.text = linkString;
NSLog(#"%#", linkLabel.text);
All I changed was linkLabel in your NSLog to linkLabel.text
Assuming like you said that linkString has a value, the second log should output the same as the first log.
EDIT: I saw your comment above, there is no need for a duplicate definition of the label as an #property and above that in the h file.
Are you sure that
NSString *linkString = self.product[#"link"];
works? Try this:
NSString *linkString = #"Test";
and use this for logging:
NSLog(#"%#", linkLabel.text);
Did you forget to hook up the linkLabel in your XIB? Is the value of linkLabel not nil?
What does NSLog(#"%#", linkLabel); print out?

How to trim off symbols from NSNumber?

Im making an iOS app to do with currency. My app receives the value of maybe: $4. This value the app receives is put into an NSNumber. The trouble is the value actualy has a $ in it. How do I trim out the $ in the NSNumber? Or would I be better of putting it into an NSString?
Use NSNumberFormatter:
// set up your number formatter
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
// get a string that you'll be converting to a NSNumber
NSString *myNumberString = [NSString stringWithFormat:#"$4"]
// convert then print to the console
NSNumber *myNumber = [numberFormatter numberFromString:myNumberString];
NSLog(#"myNumber: %#", myNumber);
This should accomplish what you're looking to do. myNumberString will need to be altered to contain whatever string you're receiving.
NSNumberFormatter Documentation: https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSNumberFormatter_Class/Reference/Reference.html

componentsJoinedByString gives me EXC_BAD_ACCESS

I have an NSMutableArray i am trying to convert into a string.
Declaring my NSMutableArray...
NSMutableArray *listData;
And later inside a method...
NSString *foo = [listData componentsJoinedByString:#"|"];
NSLog(#"%#",foo);
It seems no matter what i try i keep getting EXC_BAD_ACCESS.
To make sure each element in my array was an NSString i also tried this...
NSMutableArray *mArray = [[NSMutableArray alloc] init];
for (id ln in listData) {
NSString *boo = [NSString stringWithFormat: #"%#",ln];
[mArray addObject:boo];
}
NSString *foo = [mArray componentsJoinedByString:#"|"];
NSLog(#"%#",foo);
I can manipulate my NSMutableArray by adding/deleting objects in the same method or other methods inside my class. But when i try "componentsJoinedByString" the error pops up. Does anyone have any advice or another way i can combine this array into a single NSString?
In the code you've given, there will never be an NSMutableArray for listData. At some point in your code, you'll need to create one, and presumably populate it.
Edit
Okay, so you may get into memory management problems here, so let's be a bit clearer:
You're synthesizing getters and setters for the instance variable, so it's good practice to use those to access it, they'll take care of retain and releasing appropriately.
To set listData you can simply use
self.listData = [listManage getList:[[NSUserDefaults standardUserDefaults] stringForKey:#"list_name"] list:#"LIST"];
or
[self setListData:[listManage getList:[[NSUserDefaults standardUserDefaults] stringForKey:#"list_name"] list:#"LIST"]];
if you prefer.

iPhone: Problem with incrementing NSNumber & displaying transparent images (UIImageView)

I have a problem with NSNumber: I don't understand how to increment and decrement it! I've tried int with [NSNumber intValue] and so on, but it didn't work!!!! I just want a page counter which can be converted to an NSNumber at the end.
My second problem is displaying a (partially) transparent image in an UIImageView. It has ever a (white) background.
Thanks for answering,
Le Milonkh
HI there
don't use nsnumbers, use ints. Much easier... (NSNumber is merely a wrapper for storing numbers, whereas int provides the default set of C based mathematical interfaces you are looking for, with relative ease - I'm sure you can do math with NSNumber -> although many people say NSDecimal is better. I say use floats, ints and doubles).
int pagenumber;
for(pagenumber = 0; pagenumber < 5; pagenumber++){
NSLog(#"%i", pagenumber);
}
then if you really need it in an NSNumber then do:
NSNumber *pagenumberns = [NSNumber numberWithInt:pagenumber];
In answer to your second question I have never had that problem, but try doing: [ImageView setOpaque:no] and [ImageView setBackgroundColor:[UIColor clearColor]];
Hope some of that helps.
Thank you for your answer, but I need to declare them globally in my ...ViewController.h & .m files because all my methods use them.
Is is possible to do it like that, or have I to #property and #synthesize the int?
FooViewController.h:
#interface FooViewController : UIViewController {
int *currentPage;
}
-(void)next;
-(void)changePage:(int)page;
FooViewController.m:
#implementation Post_GeheimnisViewController
#synthesize currentPage;
-(void)changePage:(int)page {
//do some stuff here
}
-(void)next {
currentPage++;
[self changePage:currentPage];
}
#end
Thank you for answering!
Le Milonkh

Easy way to set a single character of an NSString to uppercase

I would like to change the first character of an NSString to uppercase. Unfortunately, - (NSString *)capitalizedString converts the first letter of every word to uppercase. Is there an easy way to convert just a single character to uppercase?
I'm currently using:
NSRange firstCharRange = NSMakeRange(0,1);
NSString* firstCharacter = [dateString substringWithRange:firstCharRange];
NSString* uppercaseFirstChar = [firstCharacter originalString];
NSMutableString* capitalisedSentence = [originalString mutableCopy];
[capitalisedSentence replaceCharactersInRange:firstCharRange withString:uppercaseFirstChar];
Which seems a little convoluted but at least makes no assumptions about the encoding of the underlying unicode string.
Very similar approach to what you have but a little more condense:
NSString *capitalisedSentence =
[dateString stringByReplacingCharactersInRange:NSMakeRange(0,1)
withString:[[dateString substringToIndex:1] capitalizedString]];
Since NSString is immutable, what you have seems to be a good way to do what you want to do. The implementations of (NSString*)uppercaseString and similar methods probably look very much like what you've written, as they return a new NSString instead of modifying the one you sent the message to.
I had a similar requirement, but it was for characters within the string. This assuming i is your index to the character you want to uppercase this worked for me:
curword = [curword stringByReplacingCharactersInRange:NSMakeRange(i,1)
withString:[[curword substringWithRange:NSMakeRange(i, 1)] capitalizedString]];
If you profile these solutions they are much slower then doing this:
NSMutableString *capitolziedString = [NSMutableString stringWithString:originalString];
NSString *firstChar = [[capitolziedString substringWithRange:NSMakeRange(0,1)] uppercaseString];
[capitolziedString replaceCharactersInRange:NSMakeRange(0, 1) withString:firstChar];
in testing on an iphone 4 running iOS 5:
#doomspork's solution ran in 0.115750 ms
while above ran in 0.064250 ms;
in testing on an Simulator running iOS 5:
#doomspork's solution ran in 0.021232 ms
while above ran in 0.007495 ms;
Aiming for maximum readability, make a category on NSString and give it this function:
NSString *capitalizeFirstLetter(NSString *string) {
NSString *firstCapital = [string substringToIndex:1].capitalizedString;
return [string stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:firstCapital];
}
Then in your code where you want it:
NSString *capitalizedSentence = capitalizeFirstLetter(dateString);
This kind of code rarely belongs in the spot where you need it and should generally be factored away into a utility class or a category to improve legibility.

Resources