Crash when accessing NSMutableDictionary by string, in 2 different ways? [closed] - ios

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have the following method:
-(QFFriend*)getFriendById:(NSString*)fid
{
TFLog(#"NList %#", self.nFlist);
TFLog(#":%#:%#:", #"3", fid);
TFLog(#"%#", [self.nFlist valueForKey:#"3"]);
// TFLog(#"%#", [self.nFlist valueForKey:fid]);
}
And when I run it WITH the comment, I get this result: (and crash because I left out the return)
2013-04-12 07:39:49:972 QF[42881:2311] NList {
2 = "<QFFriend: 0x1dd61970>";
3 = "<QFFriend: 0x1dd76570>";
4 = "<QFFriend: 0x1dd84a70>";
7 = "<QFFriend: 0x1dd70760>";
}
2013-04-12 07:39:49:974 QF[42881:2311] :3:3:
2013-04-12 07:39:49:976 QF[42881:2311] <QFFriend: 0x1dd76570>
However, If I uncomment that line I get another crash, can someone explain what could be wrong?
2013-04-12 07:43:28:736 QuizFuzz[42912:2311] NList {
2 = "<QFFriend: 0x1c5888c0>";
3 = "<QFFriend: 0x1c5a5c30>";
4 = "<QFFriend: 0x1c5acaf0>";
7 = "<QFFriend: 0x1c5badf0>";
}
2013-04-12 07:43:28:738 QF[42912:2311] :3:3:
2013-04-12 07:43:28:740 QF[42912:2311] <QFFriend: 0x1c5a5c30>
2013-04-12 07:43:28.741 QF[42912:907] -[__NSCFNumber length]: unrecognized selector sent to instance 0x1d8521b0
2013-04-12 07:43:28:754 QF[42912:2311] ERROR: -[__NSCFNumber length]: unrecognized selector sent to instance 0x1d8521b0
2013-04-12 07:43:28.756 QF[42912:907] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance 0x1d8521b0'
How can the two last calls not be equivalent? I send in a string in both cases!

the error is:
-[__NSCFNumber length]: unrecognized selector sent to instance
which means fid is a NSNumber not NSString
also, you should use objectForKey: rather valueForKey: to get object from dictionary
so try this
[self.nFlist valueForKey:[fid stringValue]]

I'm not sure why you are getting two different crashes when using what would seem to be very similar code. But if you want to fix the crashes, I believe the call you are looking for is:
[self.nFlist objectForKey:#"3"];
NSDictionary Class Reference
/* update */
Actually, after reading your crash logs more and looking at the TFLogs. I would take a guess that the fid object that is getting passed in is an NSNumber, not an NSString like you expect. To confirm this, you could log out: TFLog(#"fid.class: %#", fid.class); This logs the class, not the description, so you can see what you have. NSNumber with the value 3 and NSString with the value #"3" would both log out as 3.

Related

Parse incrementKey making iOS app to crash

I am trying to increment by 1 a column called "ThumbsDown" in my Parse Database, but the line of code where I perform such increment makes the app to crash. The column is of type "Number".
PFQuery *downvoteUser = [PFQuery queryWithClassName:#"UserRating"];
[downvoteUser whereKey:#"User" equalTo:PFUser.currentUser.username];
NSArray *downVote = [downvoteUser findObjects];
NSLog(#"objectID : %#", [downVote valueForKey:#"objectId"]);
NSLog(#"ThumbsDown : %#", [downVote valueForKey:#"ThumbsDown"]);
// Here we update the Rated column in Event Class
PFObject *CurrentUserThumbsDown = [PFObject objectWithoutDataWithClassName:#"UserRating" objectId:[downVote valueForKey:#"objectId"]];
[CurrentUserThumbsDown incrementKey:#"ThumbsDown"];
[CurrentUserThumbsDown save];
According to my tests :
If I remove the incrementKey, it won't crash; but it won't do anything
The NSLogs actually return the expected values, fetched from the cloud.
I cant event print out the error from save, because it crashes before being able to catch it
The crash error that I get is this one:
2020-01-19 19:25:41.024887+0100 Sporteve[39724:418054] Warning: A long-running operation is being executed on the main thread.
Break on warnBlockingOperationOnMainThread() to debug.
2020-01-19 19:25:41.025422+0100 Sporteve[39724:418243] -[__NSSingleObjectArrayI length]: unrecognized selector sent to instance 0x600001572ef0
2020-01-19 19:25:41.027731+0100 Sporteve[39724:418243] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSingleObjectArrayI length]: unrecognized selector sent to instance 0x600001572ef0'
EDIT/HINT:
If I change the objectID in the PFObject for a real objectId from the database, it actually works, so the problem must be in the NSArray.
Super simple.
#Vadian asked me the correct question. I am retrieving just 1 object, so the correct line would be this one :
PFObject *CurrentUserThumbsDown = [PFObject objectWithoutDataWithClassName:#"UserRating" objectId:[downVote[0] valueForKey:#"objectId"]];
EDIT:
A better idea provided in the comments below is to to just getFirstObject, and it is a better idea:
PFObject *CurrentUserThumbsDown = [downvoteUser getFirstObject];

Creating nested json

I'm trying to create a nested json using the sequent code. The problem is that when the system executes the line
jsonOnCloud = #{
#"server_item_id": i.ref_cloud_id,
#"client_item_id": extra.id_item,
#"extras": extras
};`
generates me the error
-[__NSDictionaryI length]: unrecognized selector sent to instance 0x110cefc0
2016-05-25 12:32:25.733 LiSchool[3145:745044] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI length]: unrecognized selector sent to instance 0x110cefc0'
this is the code
NSMutableArray *extras = [[NSMutableArray alloc] init];
NSDictionary *jsonOnCloud = [[NSDictionary alloc] init];
NSDictionary *extraJson = #{
#"action": action,
#"client_id": extra.id.stringValue,
#"id_repo": g.id_repository,
#"page": extra.page.stringValue,
#"creation_utc_client": extra.datetime_creation
};
[extras addObject:extraJson];
jsonOnCloud = #{
#"server_item_id": i.ref_cloud_id,
#"client_item_id": extra.id_item,
#"extras": extras
};
You have not provided enough information for us to be able to help you. the code you say is crashing:
jsonOnCloud = #{
#"server_item_id": i.ref_cloud_id,
#"client_item_id": extra.id_item,
#"extras": extras
};
Refers to objects that you don't describe.
What is i? And what is its ref_cloud_id property? What is extra, and what is its id_item property? It looks like extras is an empty mutable dictionary, so that part won't be the problem, but either i.ref_cloud_id or extra.id_item could cause a crash, depending on what those variables contain.
(To other readers: I realize this is not a complete answer, but I need the formatting of an answer in order to show code. Comments do not allow any formatting. Please forgive my mis-use of an "answer" in this case.)

Loop through array then compare current object to string

I'm trying to iterate through an NSArray and check if an objectAtIndex is equal to a string.
NSLog(#"%#", myArray) // 3 items. 1 of them is "a"
for (id object in myArray)
{
NSLog(#"What"); // 3 times
if ([object isEqual:#"a"]) {
NSLog(#"Hello"); // Never gets executed
}
}
The problem is, the NSLog in the if statement never gets executed?
Edit
(
(
a
),
(
01
),
(
a
),
(
03
)
)
When I set it to isEqualToString, I get this error:
2015-03-30 14:42:54.206 MyApp[1575:50954] -[__NSArrayM isEqualToString:]: unrecognized selector sent to instance 0x7fe721ce3bf0
2015-03-30 14:42:54.215 MyApp[1575:50954] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM isEqualToString:]: unrecognized selector sent to instance 0x7fe721ce3bf0'
Your problem is that you have an array that contains three sub-arrays, each of which contain, what is presumably, a single string. You can tell this because of the extra ()'s around the strings in the log output, and by the fact that it's telling you that you tried to send a selector to __NSArrayM.
Here is a quick fix:
NSLog(#"%#", myArray) // 3 items. 1 of them is "a"
for (NSArray *array in myArray)
{
NSLog(#"What"); // 3 times
if ([array.firstObject isEqualToString:#"a"])
{
NSLog(#"Hello"); // Never gets executed
}
}
But as others have pointed out you probably want to use isEqualToString: since it will be more performant.
You may also want to reconsider the code that is generating this nested array structure, or the schema that you're using in general, because it seems... unnecessary. Without further information there's not much to be done.

how to access single JSON value for key in Objective-C

I am new to Obj-C and somehow I can get the output of a JSON-Request due to difficulties with arrays, dictionareis and syntax. It would be great if someone could get me on my way.
NSLog(#"JSON Feed: %#", self.classified);
NSDictionary *test = self.classified;
NSLog(#"andy %#", [test objectForKey:#"text"]);
this throws an exception :
JSON Feed: (
{
text = "test text";
}
)
2014-06-05 17:25:28.170 Nerdfeed[2321:4107] -[__NSCFArray objectForKey:]: unrecognized selector sent to instance 0x10b988da0
2014-06-05 17:25:28.173 Nerdfeed[2321:4107] * Terminating app due to uncaught exception
I now tried to find a solution for hours but cant fix it. Thank you so much for any help.
self.classified seems to be a NSArray with a single item (and not a NSDictionary). Try [[self.classified firstObject] objectForKey:#"text"]

AFNetworking does not returns NSString if the value is contains only digits

I'm trying to receive a certain value in a json using AFNetworking. The value only contains digits and I want to receive it as a NSString. When I compare the received value, I get a exception (exception is also mentioned later in this post)
here is the coding producing the error.
NSArray *overallGameResultsArray = [resultDictionary valueForKey:#"overall_game_results"];
winCountDictionary = [[NSDictionary alloc] init];
for (NSDictionary *gameResultsDictionary in overallGameResultsArray)
{
NSString *userId = [gameResultsDictionary valueForKey:#"winner_user_id"];
NSString *winCount = [gameResultsDictionary valueForKey:#"win_count"];
if ([winCount isEqualToString:#"0"])
{
NSLog(#"0 wins");
}
}
I don't get the exception if the "if comparison" is commented. The win_count only consists of digits in the jSON response.
Following is the exception error I'm getting.
2012-10-10 15:41:35.086 FMB[3549:c07] -[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x7230af0 2012-10-10 15:41:35.086 FMB[3549:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x7230af0'
*** First throw call stack: (0x1638012 0x1345e7e 0x16c34bd 0x1627bbc 0x162794e 0x11e03 0x20583 0x1fab4 0x245053f 0x2462014 0x24527d5 0x15deaf5 0x15ddf44 0x15dde1b 0x26997e3 0x2699668 0x28d65c 0x2512 0x2445) libc++abi.dylib: terminate called throwing an exception
i think you'll have to do :
NSString *winCount=[NSString stringWithFormat:#"%d",[[gameResultsDictionary valueForKey:#"win_count"]intValue];
With this, you get the number value into the winCount NSString, and then you can use isEqualToString method
I suppose you use JSON. Then the type of the object is determined by JSON encoding. If there are " around, it's a string. If it's a number and you want string there, change how the data is encoded on the server.
However, in this context, using a number makes more sense. You should change the implementation in the following way.
NSNumber* winCount = [gameResultsDictionary valueForKey:#"win_count"];
if ([winCount intValue] == 0) { //this would actually work for both NSNumber and NSString
NSLog(#"0 wins");
}
Comparing numbers using string comparison is always a hint that you are doing something wrong.
The exception is thrown because you expect an object to be an NSString but actually is an NSNumber, so you try to call isEqualToString: on the NSNumber which doesn't implement the method.
Since you know that winCount is always a number and apparently the JSON deserializer that AFNetworking uses box the numbers in the response into NSNumber objects, you could easily grab a string out of the object like this:
NSString *winCount = [[gameResultsDictionary valueForKey:#"win_count"] stringValue];
Now you have a string representation of your number and you can therefor perform isEqualToString:
Also note that a more elegant solution might be to receive your objects as ids, find their class and do a comparison based on the class determined.

Resources