NSDecimalNumbers in Array Causing "Unrecognized Selector..." messages - ios

Ive been playing around with obj-c for a few months now and feel comfortable with a lot of things but cant make sense of something that seems very simple. I need to be able to go from an NSString split into an array then get the NSDecimalNumbers from that array. If I try to perform any calculations, I get an "unrecognized selector sent to instance." If I simply print each decimal number everything goes smoothly. If I put the values manually into NSDecimalNumbers rather than pulling from the array that also works. The error and code are below.
2013-10-14 15:54:42.174 test[30829:c07] -[__NSCFString
decimalNumberByAdding:]: unrecognized selector sent to instance
0x75a81f0 2013-10-14 15:54:42.176 test[30829:c07] * Terminating app
due to uncaught exception 'NSInvalidArgumentException', reason:
'-[__NSCFString decimalNumberByAdding:]: unrecognized selector sent to
instance 0x75a81f0'
* First throw call stack: (0x1c90012 0x10cde7e 0x1d1b4bd 0x1c7fbbc 0x1c7f94e 0x2075 0x10e1705 0x152c0 0x15258 0xd6021 0xd657f 0xd56e8
0x44cef 0x44f02 0x22d4a 0x14698 0x1bebdf9 0x1bebad0 0x1c05bf5
0x1c05962 0x1c36bb6 0x1c35f44 0x1c35e1b 0x1bea7e3 0x1bea668 0x11ffc
0x1bfd 0x1b25) libc++abi.dylib: terminate called throwing an exception
-(IBAction)buttonPushed: (id) sender
{
NSString* s = #"25.55, 109.24";
NSArray* a = [s componentsSeparatedByString: #" "];
NSDecimalNumber* dec1 = [a objectAtIndex: 0];
NSDecimalNumber* dec2 = [a objectAtIndex: 1];
NSDecimalNumber* sum = [dec1 decimalNumberByAdding: dec2];
statusText.text = [NSString stringWithFormat: #"%#", sum, nil];
}

NSDecimalNumber* dec1 = [a objectAtIndex: 0];
doesn't give you a NSDecimalNumber object. It gives you a string (which was created via the call to componentsSeparatedByString)
Try doing this:
NSDecimalNumber* dec1 = [NSDecimalNumber decimalNumberWithString: [a objectAtIndex: 0]];
and see if you have better luck.

you never created a NSDecimalNumber object
NSArray* a = [s componentsSeparatedByString: #", "];
will of course create an aray of strings.
Just because you type the pointer as decimal number, doesnt make the obejct to be one
NSDecimalNumber* dec1 = [a objectAtIndex: 0];
dec1 is still a NSString. Try
NSDecimalNumber* dec1 = [NSDecimalNumber decimalNumberWithString:[a objectAtIndex: 0]];
NSDecimalNumber* dec2 = [NSDecimalNumber decimalNumberWithString:[a objectAtIndex: 1]];
NSDecimalNumber* sum = [dec1 decimalNumberByAdding: dec2];
statusText.text = [NSString stringWithFormat: #"%#", sum];

When you call [a objectAtIndex: 0] that is just returning a string, that you're trying to cast to a NSDecimalNumber.
Instead, try using something like this:
-(IBAction)buttonPushed: (id) sender
{
NSString* s = #"25.55, 109.24";
NSArray* a = [s componentsSeparatedByString: #", "];
NSDecimalNumber* dec1 = [NSDecimalNumber decimalNumberWithString:[a objectAtIndex: 0]];
NSDecimalNumber* dec2 = [NSDecimalNumber decimalNumberWithString:[a objectAtIndex: 1]];
NSDecimalNumber* sum = [dec1 decimalNumberByAdding: dec2];
statusText.text = [NSString stringWithFormat: #"%#", sum, nil];
}
Also note that I'm splitting the string with ", " and not just " ", otherwise the first string will be "25.55,"
See the NSDecimalNumber documentation for the details: https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/NSDecimalNumber_Class/Reference/Reference.html#//apple_ref/occ/clm/NSDecimalNumber/decimalNumberWithString:

Related

Remove negative symbol (-) from NSDecimalNumber gives me an error

I have an array with NSDecimalNumbers inside. I will do a check to see if that number is a negative number. If it is, I want to remove the negative sign (-). Here is my code:
NSString *amount = [myArray objectAtInde:2]; // Is a NSDecimalNumber with value of: -397.67
if ([amount doubleValue] < 0) {
amount = [amount stringByReplacingOccurrencesOfString:#"-" withString:#"- $"];
}
When I do that, I get the following error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSDecimalNumber stringByReplacingOccurrencesOfString:withString:]: unrecognized selector sent to instance 0x7fcaf94eff80'
Add below method in your source file
// multiplies number with -1 if it is less than zero else returns the same
- (NSDecimalNumber *)abs:(NSDecimalNumber *)num
{
if ([num compare:[NSDecimalNumber zero]] == NSOrderedAscending)
{
// Number is negative. Multiply by -1
NSDecimalNumber * negativeOne = [NSDecimalNumber decimalNumberWithMantissa:1
exponent:0
isNegative:YES];
return [num decimalNumberByMultiplyingBy:negativeOne];
}
else
{
return num;
}
}
And convert instance of NSDecimalNumbers to abs value without doing any type conversion as-
NSDecimalNumbers *number = [myArray objectAtInde:2];
number = [number abs:number];
the number returned will contain abs value in NSDecimalNumbers format.
Try this,
NSDecimalNumber *amountNumber = [myArray objectAtIndex:2]; // Is a NSDecimalNumber with value of: -397.67
NSString *stringWithDollarSymbol = [self addDollarSymoblForNumber:amountNumber];
You can assign the stringWithDollarSymbol to label
- (NSString *)addDollarSymoblForNumber:(NSDecimalNumber *)decimalNum
{
NSString *modifiedString = #"";
if (decimalNum) {
NSString *numberInStringForm = [decimalNum stringValue];
if ([decimalNum doubleValue] < 0) { //adds dollor symbol for negative numbers
modifiedString = [numberInStringForm stringByReplacingOccurrencesOfString:#"-" withString:#"- $"];
}
else //adds dollor symbol for positive numbers
{
modifiedString = [NSString stringWithFormat:#"$ %#",modifiedString];
}
}
return modifiedString;
}
EDIT
More Better Approach using NSNumberFormatter:
- (NSString *)formatNumberBasedOnCurrentLocale:(NSDecimalNumber *)number
{
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setLocale:[NSLocale currentLocale]];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSString *result = [formatter stringFromNumber:number];
if (result.length >0) {
return result;
}
return nil;
}
Please add line,
if ([amount doubleValue] < 0) {
amount=[NSString stringWithFormat:#"%#",[myArray objectAtIndex:2]];//add line
amount = [amount stringByReplacingOccurrencesOfString:#"-" withString:#""];
}
it may be work for you,
I just used your code & it's working fine at my end.
Tried below thing,
NSString *amount = #"-397.67";//[myArray objectAtInde:2]; // Is a NSDecimalNumber with value of: -397.67
if ([amount doubleValue] < 0) {
amount = [amount stringByReplacingOccurrencesOfString:#"-" withString:#""];
}
Try it at your end.
If nothing will work then multiply your negative float value with -1 & you will get positive number. If that is your requirement.
Your [myArray objectAtInde:2] is a NSDecimalNumber rather than NSString, try this:
NSDecimalNumber *amountNumber = [myArray objectAtInde:2];
NSString *amount = [NSString stringWithFormat:#"%#", amountNumber];
Maybe you should try this one:
NSString *amount = #(ABS([myArray[2] doubleValue])).stringValue ; // Is a NSDecimalNumber with value of: -397.67
If your intention is to rescue from the negative then just simply convert the value into an absolute value.
NSString *amount = [myArray objectAtIndex:2]; // Is a NSDecimalNumber with value of: -397.67
NSLog(#"The value is : %#",[NSString stringWithFormat:#"%.2f", fabs([amount doubleValue])]);
The value is: 397.67

rangeOfString method call causing unrecognized selector error

I am accessing the address book contacts, and then running a for loop on all of the contacts. The loop's main purpose is to access the First Name and Phone Number values of the user's address book contacts and place those values into NSString objects.
All of the above works perfectly. My problem is that I need to execute specific code if the phone number data contains this string: _$!<Mobile>!$_
So I setup a rangeOfString method call on the object that contains the phone number data and this is causing problems.
Here is what prints to the console once I added the rangeOfString method call to my code:
2014-01-18 12:10:49.190 PhotoTest1[1244:60b] -[__NSCFType rangeOfString:]: unrecognized selector sent to instance 0x14e9ac90
2014-01-18 12:10:49.193 PhotoTest1[1244:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType rangeOfString:]: unrecognized selector sent to instance 0x14e9ac90'
*** First throw call stack:
(0x2f8f6f4b 0x39d376af 0x2f8fa8e7 0x2f8f91cb 0x2f8fa478 0x55e29 0x3206e37b 0x3206e139 0x32117e27 0x3215449b 0x32152dd3 0x32151e25 0x3232dcb3 0x3209e713 0x3209e6b3 0x3209e691 0x3208a11f 0x3209e107 0x3209ddd9 0x32098e65 0x3206e79d 0x3206cfa3 0x2f8c2183 0x2f8c1653 0x2f8bfe47 0x2f82ac27 0x2f82aa0b 0x34551283 0x320ce049 0x54495 0x3a23fab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
And here is all of my code starting with the for loop. The error prints to the console as soon as it gets to "if([phoneNumber rangeOfString:#"+"].location == NSNotFound)":
for (i = 0; i < [allContacts count]; i++)
{
Person *person = [[Person alloc] init];
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
NSString *firstName = (__bridge_transfer NSString
*)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *phoneNumber = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
person.firstName = firstName;
person.phoneNumber = phoneNumber;
NSLog(#"%#", phoneNumber);
//MOBILE PHONE PSEUDOCODE STARTS HERE
// If the value of phoneNumber contains the text “_$!<Mobile>!$_” , then we want to grab a substring out of it.
if([phoneNumber rangeOfString:#"_$!<Mobile>!$_"].location == NSNotFound) {
NSLog(#"Not a mobile phone number");
} else {
NSLog(#"It is a mobile phone number");
// If the value of phoneNumber contains a “+”, then grab the substring that starts with the + and then the next additional 10 spaces and place the substring in the mobilePhoneNumber object. (Which will grab the + sign and the 10 digit phone number. )
if([phoneNumber rangeOfString:#"+"].location == NSNotFound) {
NSLog(#"Phone number does not start with a +");
} else {
NSLog(#"Phone number does start with a +");
NSString *subString = [phoneNumber substringWithRange: NSMakeRange(0, [phoneNumber rangeOfString: #"+"].location)];
NSLog(#"%#", subString);
}
}
//PFQUERY CODE TESTING!!!
}
}
}
Thanks for the help.
The phone Number is no string . it is defined as a multival as there can be 0..x numbers there.
you can't just treat it as a string . you need to enumerate through the multival\
e.g. to get the first of ANY kind
ABMultiValueRef phoneEntries = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSMutableArray *numbers = [NSMutableArray array)];
for(int i = 0; i < ABMultiValueGetCount(phoneEntries); i++) {
NSString *number = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(phoneEntries, i))];
// Do what you want with the number
[numbers addObject:number];
}
CFRelease(phoneEntries);

Error in string length

I have a table view which may contain number of data.
When user select one particular cell I set Id in string based on that selection. And then I am trying to find length of that string. But I am getting error in that. When I print that string it print its value.
Here is my code.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSArray *charityArray = [dataArray objectAtIndex:indexPath.row];
charityId=[charityArray objectAtIndex:0];
NSLog(#"charityId%#",charityId);
NSLog(#"charitylen%d",[charityId length]);
}
and here is log screen.
2013-12-04 14:47:13.897 GratZeez[2178:a0b] charityId3
2013-12-04 14:47:13.897 GratZeez[2178:a0b] -[__NSCFNumber length]: unrecognized selector sent to instance 0xd174070 2013-12-04 14:47:13.899
GratZeez[2178:a0b] * Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[__NSCFNumber length]:
unrecognized selector sent to instance 0xd174070'
declaration of charityId:
#import <UIKit/UIKit.h>
#interface ExsitingCharityViewController : UIViewController<UITableViewDelegate,UITableViewDataSource,UITextFieldDelegate>
{
NSMutableArray *dataArray,*tempArray,*searchResultArray,*nameSearchArray;
BOOL search;
NSMutableDictionary *dataDict;
CGPoint originalCenter;
NSString *charityId;
}
try this code, Convert NSNumber to NSString and then use length
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSArray *charityArray = [dataArray objectAtIndex:indexPath.row];
charityId = [charityArray objectAtIndex:0];
NSString *charityString = [charityId stringValue];
NSLog(#"charityString = %#", charityString);
NSLog(#"charityString length = %d",[charityString length]);
}
As you post, charityId s not a NSNumber formatted type value.
If you want to know to length convert in to NSString formate,
Like, NSString* str = [NSString stringwithFormat:#"%#", charityId];
then you get length.
As the error log shows, you are sending the length message to a NSNumber object. According to your post, you seem to be trying to send it to a NSString but it is not a NSString.
-[__NSCFNumber length]: unrecognized selector sent to instance 0xd174070'
If you wish to use the %d string format specifier with an NSNumber you should convert the NSNumber object to an integer first:
NSLog(#"charityId%d",[charityId intValue]);
use this code for NSNumber to NSString
NSString *strId=[NSString StringWithFormat#"%d", charityId];
NSLog(#"charitylen%d",[strId length]);
If you are trying to NSLog an NSNumber do the following, replace this:
NSLog(#"charitylen%d",[charityId length]);
With this:
NSString *myString = [charityId stringValue];
NSLog(#"charitylen%#", myString);
And if you are trying to get the count of your Array use the following:
NSLog(#"charitylen%d",[charityId count]);
Update:
I have to opinions about your case:
1- It means that you are passing an NSNumber where the called code expects an NSString or some other object that has a length method. You can tell Xcode to break on exceptions so that you see where exactly the length method gets called.
2-I think it may because your charityId is empty or never used before you NSLog it .
-[__NSCFNumber length]: unrecognized selector sent to instance it's mean you are tried to get length of a number (i.e. int, NSInteger etc). so you need to typecast.
you can do it either using [NSString stringWithFormat:#"%d", charityId] or [charityId stringValue]
so just do below
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSArray *charityArray = [dataArray objectAtIndex:indexPath.row];
charityId=[charityArray objectAtIndex:0];
NSString *charityIdString=[NSString stringWithFormat:#"%d", charityId];
NSLog(#"charityId%#",charityIdString);
NSLog(#"charitylen%d",[charityIdString length]);
}

How to fix this mutating error?

I'm getting this error:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to mutate immutable object with replaceCharactersInRange:withString:'
But I can't figure out what immutable object I'm mutating.
NSRange subRange = [self.label.text rangeOfString: #"="];
int numA = 5;
int numB = 3;
NSMutableString *mixed = [NSString stringWithFormat: #"%i %i", numA, numB];
NSMutableString *string = [NSString stringWithString: self.label.text];
subRange = [string rangeOfString: #"="];
if (subRange.location != NSNotFound)
[string replaceCharactersInRange:subRange withString:mixed];
Your NSMutableString creation calls aren't balanced properly. You're promising the compiler that you're creating a NSMutableString but you ask an NSString to create an instance.
For example:
NSMutableString *mixed = [NSString stringWithFormat: #"%i %i", numA, numB];
needs to be:
NSMutableString *mixed = [NSMutableString stringWithFormat: #"%i %i", numA, numB];
Your NSMutableStrings are actually instances of NSString. This is runtime detail, though there should at least be a warning for those lines. Change to:
NSMutableString *string = [self.label.text mutableCopy];
You need to create a NSMutableString like this:
[NSMutableString stringWithString: self.label.text];

Get Row from NSArray

Hello i get a json that looks like this:
features: (
{
attributes = {
Gecontroleerd = Ja;
};
geometry = {
x = "5.968097965285907";
y = "52.50707112779077";
};
}
)
From this code:
NSDictionary *root = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
NSArray *data = [root objectForKey:#"features"];
NSLog(#"features: %#", data );
for (NSArray *row in data) {
NSString *latitude = row[5];
NSString *longitude = row[7];
NSString *crimeDescription = #"test";
NSString *address = #"banaan";
And u need to x values 5.968097965285907 for latitude
and y values 52.50707112779077 for longitude
But i get this error:
[__NSCFDictionary objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x14831450
2012-11-14 10:10:59.000 ArrestPlotter[6330:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x14831450'
*** First throw call stack:
(0x1860012 0x1655e7e 0x18eb4bd 0x184fbbc 0x184f94e 0x2dbc 0x3b8f 0x1cc1e 0x16696b0 0xfa0035 0x17e3f3f 0x17e396f 0x1806734 0x1805f44 0x1805e1b 0x224a7e3 0x224a668 0x4a765c 0x25bd 0x24e5 0x1)
libc++abi.dylib: terminate called throwing an exception
(lldb)
Does anyone wich row i need to select?
I guess that the only thing is that the row number needs to be changed. Or maybe there should be something like this : [1][5]. Im not quite sure how this works
NSArray *data = [root objectForKey:#"features"];
NSLog(#"features: %#", data );
for (NSDictionary *dic in data) {
NSDictionary geometry = [dic objectForKey:#"geometry"];
// Do what you want..
NSString *myAwesomeX = [geometry objectForKey:#"x"];
NSString *myAwesomeY = [geometry objectForKey:#"y"];
}
The problem here is that you are trying to send a selector message to object row, that is in memory a NSDictionary (NSCFDictionary?) object, and you are trying to manage it like a NSArray.
The method objectAtIndexedSubscript (is underlying called by row[5] and row[7]) exists in NSDictionary, but no in NSArray.
Change
for (NSArray *row in data) {
by
for (NSDictionary *row in data) {
Also, you have to change the management of data inside for, look at the result of your log statement and act accord whit it.
I hope this will help!

Resources