NSNumberFormatter conversion remove the decimal for small values - objective-c

Our quality-assurance team detect a defect. When they write 0.095 or 0,095 in a currency field, the NSNumberFormatter converts the content to 95.
This is the code we're using:
+ (NSNumber *) getNumberWithDecimalFromString:(NSString*) theSource
{
if ([TSCommons isEmpty:theSource])
return [[NSNumber alloc] initWithInt:0];
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
if ([theSource rangeOfString:#","].location != NSNotFound) {
[formatter setDecimalSeparator:#","];
[formatter setCurrencyDecimalSeparator:#"."];
} else if ([theSource rangeOfString:#"."].location != NSNotFound) {
[formatter setDecimalSeparator:#"."];
[formatter setCurrencyDecimalSeparator:#"."];
}
NSNumber *tmp = [formatter numberFromString:theSource];
[formatter release];
return [tmp retain];
}
The locale is es_ES
Any idea about this unexpected behavior?
To introduce more information about this problem, because come back again after the last XCode update I prepared a test
- (void) testNumberFormatter
{
NSLog(#"%f",[[TSCommons getNumberWithDecimalFromString:#"41,1"] doubleValue]);
NSLog(#"%f",[[TSCommons getNumberWithDecimalFromString:#"41,12342"] doubleValue]);
NSLog(#"%f",[[TSCommons getNumberWithDecimalFromString:#"41,12"] floatValue]);
NSLog(#"%f",[[TSCommons getNumberWithDecimalFromString:#"41,123"] floatValue]);
NSLog(#"%f",[[TSCommons getNumberWithDecimalFromString:#"41,1234"] floatValue]);
NSLog(#"%f",[[TSCommons getNumberWithDecimalFromString:#"41,1234234"] doubleValue]);
}
The result on the Console is the following:
41.100000
41.123420
41.119999
41123.000000
41.123402
41.123423
Thanks!!

NSString* theSource = #"0.095";
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
if ([theSource rangeOfString:#","].location != NSNotFound) {
[formatter setDecimalSeparator:#","];
[formatter setCurrencyDecimalSeparator:#"."];
} else if ([theSource rangeOfString:#"."].location != NSNotFound) {
[formatter setDecimalSeparator:#"."];
[formatter setCurrencyDecimalSeparator:#"."];
}
NSNumber *tmp = [formatter numberFromString:theSource];
NSLog(#"get Number %# - %lf %lf", tmp, [theSource doubleValue], [tmp floatValue]);
// output get Number 0.095 - 0.095000 0.095000

Related

How to compare the strings?

In my project i am adding many words to a list from another view controller and i need to check that the words cannot be same in the list.
Here is the code ,please help where i need to do that
-(IBAction)save:(id)sender{
if ([listName.text isEqualToString:#""]) {
UIAlertView *error = [[UIAlertView alloc] initWithTitle:nil message:#"Please enter List Name." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles: nil];
[error show];
} else if (self.newlist) {
if (listName.text.length > 0 ) {
[[UIApplication sharedApplication] cancelAllLocalNotifications];
NSDate *currDate = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"YYYY-MM-dd"];
NSString *dateString = [dateFormatter stringFromDate:currDate];
if (notification.on ) {
NSString *dateStr = [[NSString alloc] initWithFormat:#"%# %#",dateString, time.text ];
[self saveList:dateStr:dateString];
[self saveListImages];
[self getlistdata];
}else {
[self saveList:#"2000-01-01 00:00":dateString];
}
}else{
[listName becomeFirstResponder];
}
}
}
Add your string in a mutable array and call below comparator to check for duplicates. Below code ensures case insensitive checks so it won't allow TEST and test go in the same array.
NSMutableArray *myArray = [NSMutableArray arrayWithArray:#[#"TEST", #"Data"]];
NSString *testString = #"Test";
NSInteger index = [myArray indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
return (BOOL)([obj caseInsensitiveCompare:testString] == NSOrderedSame);
}];
if (index != NSNotFound) {
NSLog(#"String already entered. Throw error");
} else {
[myArray addObject:testString];
}
NSOrderedSet *uniqueWordSet = [NSOrderedSet orderedSetWithArray:arrayWithDuplicates];
NSArray *unwiqueWordList = uniqueWordSet.array; // If you need it as array

How to use the current time in Objective-C

How should I import the current time into my app and use it to do some calculation?
What my app do is that it use the current time and do some calculation and then give me some percentage.
How are you wanting to get the time (in milliseconds?)
There's a few questions on here already - like this one, which should help point you in the right direction.
From the Apple Docs for NSDate
Creates and returns an NSDate object set to the given number of
seconds from the first instant of 1 January 1970, GMT.
[[NSDate date] timeIntervalSince1970];
// use this method to get current time as per your iPhone's time format
+(NSString *)getCurrTime
{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setLocale:[NSLocale currentLocale]];
[formatter setDateStyle:NSDateFormatterNoStyle];
[formatter setTimeStyle:NSDateFormatterShortStyle];
NSString *dateString = [formatter stringFromDate:[NSDate date]];
NSRange amRange = [dateString rangeOfString:[formatter AMSymbol]];
NSRange pmRange = [dateString rangeOfString:[formatter PMSymbol]];
BOOL is24h = (amRange.location == NSNotFound && pmRange.location == NSNotFound);
if (is24h == YES) {
[formatter setDateFormat:#"HH:mm"];
}
else
{
[formatter setDateFormat:#"hh:mm a"];
}
dateString =[formatter stringFromDate:[NSDate date]];
NSLog(#"%#\n",(is24h ? #"YES" : #"NO"));
return dateString;
}

Sorting a PFQuery by counting objects in array

What I am doing is in my Parse query, I check to see which posts have been check marked (liked) in the last 7 days. I then remove the dates of those that haven't. This is working fine. Now my problem is that I need to sort them in my UITableView in descending order of how many dates are in the array but my sortedArrayUsingComparator isn't working. Im new to Objective C so its probably something easy but idk. Here's my code
- (PFQuery *)queryForParse {
PFQuery *query1 = [PFQuery queryWithClassName:self.parseClassName];
//[query1 selectKeys: [NSArray arrayWithContentsOfFile:[ NSString #"checkMark"]]];
[query1 whereKey:#"location" nearGeoPoint:[PFGeoPoint geoPointWithLatitude:[LocationController sharedSingleton].locationManager.location.coordinate.latitude longitude:[LocationController sharedSingleton].locationManager.location.coordinate.longitude] withinMiles:50];
[query1 findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error){
placesArray = [[NSMutableArray alloc] initWithArray:objects];
NSMutableArray *toDelete = [NSMutableArray array];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyyMMdd"];
for (PFObject *tempObject in placesArray){
checkDates = [[NSMutableArray alloc] initWithArray:[tempObject objectForKey:#"checkMarkDates"]];
for (NSString *dateString in checkDates) {
NSDate *date = [dateFormat dateFromString: dateString];
if ([date timeIntervalSinceNow] > -604800){
[toDelete addObject:dateString];
}
}
[checkDates removeObjectsInArray:toDelete];
[tempObject removeObjectsInArray:checkDates forKey:#"checkMarkDates"];
sortedArray = [placesArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSUInteger *first = [[obj1 objectForKey:#"checkMarkDates"] count];
NSNumber *f = [[NSNumber alloc] initWithInteger:first];
NSUInteger *second = [[obj2 objectForKey:#"checkMarkDates"] count];
NSNumber *s = [[NSNumber alloc] initWithInteger:second];
return [f compare:s];
}];
}
NSLog(#"%#", sortedArray);
}
[placesTable reloadData];
}];
return query1;
}
Figured it out. I had the sortedArrayUsingComparator in the for statement. I moved it out and it works fine now.

How to convert numbers into indicative string

I just want to know how can I can convert the numbers 1, 2 or 3 into First, second or Third ?
Any help would be appreciated.
Try this,
- (NSString *)getOrdinalTextFor:(NSInteger)number {
NSNumber *numberValue = [NSNumber numberWithInteger:number];
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterOrdinalStyle];
return [numberFormatter stringFromNumber:numberValue];
}
See this one may be it helps you,
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle: NSNumberFormatterSpellOutStyle];
NSString* numberString = [formatter stringFromNumber:[NSNumber numberWithInt: 3]];
NSLog(#"%#",numberString);
enter link description hereDownload Formatter kit from GitHub
TTTOrdinalNumberFormatter *ordinalNumberFormatter = [[TTTOrdinalNumberFormatter alloc] init];
[ordinalNumberFormatter setGrammaticalGender:TTTOrdinalNumberFormatterMaleGender];
NSNumber *number = [NSNumber numberWithInteger:2];
NSString *str = [ordinalNumberFormatter stringFromNumber:number];
NSLog(#"%#", str);
Read up this link, its very helpful: Number Formatting

How to avoid grouping separator in NSNumberFormater until 5 digits

I have an application that needs to display metric units in millimeters and based on the research that I have done (e.g. http://physics.nist.gov/cuu/pdf/sp811.pdf), it is recommended that you don't add grouping separators until you have 5 digits. Is this possible with NSNumberFormatter? I know I could test the value and enable/disable grouping based on its size but I would rather use the appropriate configuration for the NSNumberFormatter if it exists. (BTW, I am on Mac OS X) So for example:
3456 should be shown as 3456 mm
10234 should be shown as 10,234 mm (assuming comma is the grouping separator)
I have read the Apple docs and didn't see anything. I experimented with different searches to find the answer on Stackoverflow but couldn't find a similar question.
Here is how I am currently setting up my NSNumberFormatter:
if (numberFormatter == nil) {
numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setRoundingMode:NSNumberFormatterRoundHalfUp];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setLocale:[NSLocale currentLocale]];
[numberFormatter setMinimumFractionDigits:0];
[numberFormatter setMaximumFractionDigits:2];
}
NSNumber *numberInMM = [NSNumber numberWithFloat:fLenInMMs];
NSString *numberStr = [numberFormatter stringFromNumber:numberInMM];
numberStr = [numberStr stringByAppendingString:#" mm"];
long long d = fLenInMMs;
if (d>9999) {
NSNumberFormatter *numberFormatter=nil;
if (numberFormatter == nil) {
numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setRoundingMode:NSNumberFormatterRoundHalfUp];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setLocale:[NSLocale currentLocale]];
[numberFormatter setMinimumFractionDigits:0];
[numberFormatter setMaximumFractionDigits:2];
}
NSNumber *numberInMM = [NSNumber numberWithFloat:fLenInMMs];
NSString *numberStr = [numberFormatter stringFromNumber:numberInMM];
numberStr = [numberStr stringByAppendingString:#" mm"];
NSLog(#"%#", numberStr);
}
else {
NSNumber *numberInMM = [NSNumber numberWithFloat:fLenInMMs];
NSString *numberStr = [NSString stringWithFormat:#"%# mm",numberInMM];
}
EDIT
You can also subclass NSNumberFormatter and implement
- (NSString *)stringFromNumber:(NSNumber *)number
{
NSNumber *nm = [NSNumber numberWithInt:9999];
if (NSOrderedAscending==[number compare:nm]) {
return [NSString stringWithFormat:#"%# mm",number];
}
return [super stringFromNumber:number];
}