Why does Length not work on a NSString? - ios

I am trying to check the length of string, but I get unrecognized selector when the code is executed and hits the IF statement.
THE VALUE IN THE DICTIONARY IS A STRING.
NSString * checkString = [myDictionary objectForKey:#"somekey"];
NSLog(#"length: %lu", (unsigned long)[checkString length]);
if([checkString length] > 0){
}
ERROR From console:
length: 0
[__NSCFNumber length]: unrecognized selector sent to instance
For simplicity:
NSString * checkString = #"my string"; //[myDictionary objectForKey:#"somekey"];
NSLog(#"length: %lu", (unsigned long)[checkString length]);
if([checkString length] > 0){
}
length: 9
[__NSCFNumber length]: unrecognized selector sent to
instance
Why?

The error says that your instance is not a NSString but a NSNumber. That's probably because you stored a NSNumber in [myDictionary objectForKey:#"somekey"].
Try to put [yourValueThatYouThinkItsAString stringValue] in the place where you store this value.
I tried your code and I'm not getting error with it (with #"my string" value).
What you can try :
NSString *checkString = [[myDictionary objectForKey:#"somekey"] stringValue];
NSLog(#"length: %lu", (unsigned long)[checkString length]);
if([checkString length] > 0){
}
PS : in your NSLog() you've got a additional argument, remove it.

The reason the length is not working on NSString* is that it's not NSString*. Despite the cast, which Objective-C cannot verify, the object in your dictionary is NSNumber*, not NSString*. That is why the code compiles, but fails to run.
[myDictionary objectForKey:#"somekey"] call returns id, a generic object reference. That is why Objective-C must trust you when you perform a cast to NSString* that the object at "somekey" is actually a string.
It does not fail in NSLog because you made a mistake that prevents the length from being evaluated. Change NSLog to see it fail:
NSLog(#"length: %lu", (unsigned long)[checkString length]);
If you have XCode 7 or newer, you can use lightweight generics to help Objective-C with type checking. You can specify object types for keys and values in your dictionary, so that the compiler could catch invalid casts for you:
NSDictionary<NSString*,NSString*> *myDictionary = ...

Related

[NSTaggedPointerString stringValue]: unrecognised selector sent to instance in NSString comparision?

I got this error [NSTaggedPointerString stringValue]: unrecognised selector sent to instance
when I try to check NSString comparison
My code is:
if ([[[dict objectForKey:#"login"] stringValue] isEqualToString:#"1"])
{
}
Please read the error. It clearly states that the value for key login is (already) a string
if ([[dict objectForKey:#"login"] isEqualToString:#"1"])
{
}
or with more convenient key subscription syntax (available for many, many years)
if ([dic[#"login"] isEqualToString:#"1"])
{
}
The object is already a string, so you don't need to use the stringValue selector:
if ([[dict objectForKey:#"login"] isEqualToString:#"1"])
{
}
Note: comparing this with "1" is dodgy; convert it to NSNumber if it's a number.

iOS - Why does this NSString comparison blow-up? [duplicate]

This question already has an answer here:
Unrecognized selector error for isEqualToString: when setting text of a label
(1 answer)
Closed 8 years ago.
I have looked at SO for similar questions, but am open to being pointed to a duplicate.
I am receiving some JSON from a site, and I want to test for a 404 response.
I have this expression:
NSString *responseString = [json objectForKey:#"statusCode"];
NSLog(#"responseString: %#", responseString);
NSString *myString1 = #"404";
NSLog(#"%d", (responseString == myString1)); //0
NSLog(#"%d", [responseString isEqual:myString1]); //0
NSLog(#"%d", [responseString isEqualToString:myString1]); //Crash
The response string returns 404.
The first and second logs result in 0, and the 3rd crashes with this log:
[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0xb000000000001943
2015-01-29 16:23:33.302 Metro[19057:5064427] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0xb000000000001943'
statusCode is a number, not a string. The error makes this clear by telling you that you are trying to call isEqualToString on an NSNumber.
Try this:
NSInteger responseCode = [json[#"statusCode"] integerValue];
NSInteger notFoundCode = 404;
if (responseCode == notFoundCode) {
// process 404 error
}
The fact that you declared responseString as an NSString does not guarantee that [json objectForKey:#"statusCode"] will indeed return an NSString object.
Actually, the JSON parser detected an integer in your JSON data, and as such, returned an NSNumber. So you should be able to test it against a plain 404 literal using integerValue or, if you want to keep working with strings, will need to convert it first with stringValue.
Anyway, try this, it should return 1:
NSNumber *response = [json objectForKey:#"statusCode"];
...
NSLog(#"%d", [response integerValue] == 404);

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];

JSON Objective-C Parsing Fail

I have written the following code but I keep on getting nil. I have tried many different variations of this but I am failing exceptionally hard.
This is what I am getting from the server.
Two objects.
[{"description":"yolo.","name":"ye","id":1},{"description":"sMITH","name":"John","id":2}]
Any help would be greatly appreciated...... Thanks.
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:&urlResponse error:&requestError];
SBJsonParser *jsonParser = [[SBJsonParser alloc] init];
NSArray *jsonObjects = [jsonParser objectWithData:response];
NSMutableString *yolo = [[NSMutableString alloc] init];
for ( int i = 0; i < [jsonObjects count]; i++ ) {
NSDictionary *jsonDict = [jsonObjects objectAtIndex:i];
NSString *IDID = [jsonDict objectForKey:#"id"];
NSString *name = [jsonDict objectForKey:#"name"];
NSLog(#"ID: %#", IDID); // THIS DISPLAYS
[yolo appendString: IDID]; // THIS seems to be causing the new error...
[yolo appendString:#": "];
[yolo appendString: name];
NSLog(#"%#", yolo); // RETURNS NIL
}
EDIT:
currently my new error is...
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-[NSDecimalNumber length]:
unrecognized selector sent to instance 0x81b89f0'
Looks like your [jsonDict objectForKey:#"id"] is an NSNumber(or NSDecimalNumber) and not an NSString. You should change the line NSString *IDID = [jsonDict objectForKey:#"id"]; to,
id myObject = [jsonDict objectForKey:#"id"];
NSString *IDID = nil;
if ([myObject isKindOfClass:[NSNumber class]]) {
IDID = [[jsonDict objectForKey:#"id"] stringValue];
} else {
IDID = [jsonDict objectForKey:#"id"];
}
This error appeared now since earlier you were not initializing NSMutableString *yolo and you were using appendString: on a nil object. Since now it is initialized as NSMutableString *yolo = [[NSMutableString alloc] init]; it is trying to call appendString on NSMutableString object which accepts only NSString type as its inputs where as you are passing an NSNumber in it. length is a method which appendString: internally calls. So you need to change this as well.
You never initialize yolo, so it's just nil the whole time you're calling -appendString: on it. Try this:
NSMutableString *yolo = [NSMutableString string];
Have you tried initializing the NSMutableString?
NSMutableString *yolo = [[NSMutableString alloc] init];
It looks like you are not really checking the type of the data coming to your app via your JSON feed. This might be the case of random crashes when users actually use your app. It might be also a reason for rejection to the App Store, is such crashes happen during your App's review.
You should be checking the type of all objects you receive from JSON, before calling methods on them :)
By implementing best practices you will have a stable and usable app. Build data models to validate your data. You can also you a JSON data model framework like JSONModel: http://www.jsonmodel.com/
It's obvious from your data that "id" is not a string, but a number. Assigning a pointer to an NSString* doesn't magically convert it to an NSString*. And it's obvious from the exception that you got that some object is an NSDecimalNumber when you thought it would be an NSString.
So: IDID is an NSNumber*, and pretending it is an NSString* will lead to crashes.

Resources