Crash: mutating method sent to immutable object - ios

I am attempting to delete an object for a particular key in an NSMutableDictionary but the application crashes when trying to do so. Here is my code:
NSArray *allWebDictionary = [NSJSONSerialization JSONObjectWithData:webData options:0 error:nil];
self.results = [[NSMutableArray alloc] initWithArray:allWebDictionary];
for (NSMutableDictionary *dic2 in self.results) {
NSMutableArray *incidents = [dic2 valueForKey:#"incidents"];
for (NSMutableDictionary *incident in incidents) {
[incident removeObjectForKey:#"type"];
}
}
My app crashes with the following log:
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary removeObjectForKey:]: mutating method sent to immutable object'
Any ideas? Thanks in advance!

You made a mutable copy of the array, but the dictionary which is in the array is still immutable.
You need mutable containers.
Replace
NSArray *allWebDictionary = [NSJSONSerialization JSONObjectWithData:webData
options:0
error:nil];
with
NSMutableArray *allWebDictionary = [NSJSONSerialization JSONObjectWithData:webData
options:NSJSONReadingMutableContainers
error:nil];

Related

Building NSMutableArray from NSMutableDictionary resulting in NSException

I am a newbie in iOS development. I was trying to put the results of an NSMutableArray into an NSMutableString but this is resulting in an NSException.
Here is my code:
NSMutableArray *oldtableData = .......this is where I recieve card data;
NSError *error;
NSMutableData *tableDataUpdated = [[NSJSONSerialization dataWithJSONObject:oldtableData
options:0
error:&error] copy];
NSMutableDictionary *cardDictionary = [NSJSONSerialization JSONObjectWithData:tableDataUpdated options:0 error:NULL];
For converting the cardDictionary into a NSMutableArray, I am using this piece of code (which is giving me an NSException)
NSMutableArray *type = [NSMutableArray array];
NSMutableArray *last4Digits = [NSMutableArray array];
[cardDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
[type addObject:[obj valueForKeyPath:#"type"]];
[last4Digits addObject:[obj valueForKeyPath:#"last4Digits"]];
}];
But If I exclude the above code and try NSLog with this piece of code
NSLog(#"JSON: %#",cardDictionary);
Console will give a proper json result; something like this:
JSON: (
{
cardPciId = "###########";
fingerPrint = ###########;
last4Digits = 4321;
type = Mastercard;
},
{
cardPciId = "###########";
fingerPrint = ###########;
last4Digits = 1234;
type = Visa;
}
)
I am trying to convert this into two Arrays, one with all the "type"s and another one with all "last4Digits". But this is what I get
Uncaught exception: -[__NSCFArray enumerateKeysAndObjectsUsingBlock:]:
unrecognized selector sent to instance 0x7ff7060badf0
I tried to hover through StackOverFlow to find a solution but none of them seem to be working. :(
It looks like cardDictionary is actually an NSArray instance containing the dictionaries. So, you should iterate through the array, and get type and last4Digits from each dictionary using objectForKey instead of valueForKeyPath:
NSArray *cardDictionaries = [NSJSONSerialization JSONObjectWithData:tableDataUpdated options:0 error:NULL];
NSMutableArray *type = [NSMutableArray array];
NSMutableArray *last4Digits = [NSMutableArray array];
[cardDictionaries enumerateObjectsUsingBlock:^(NSDictionary *cardDictionary, NSUInteger idx, BOOL *stop) {
[type addObject:[cardDictionary objectForKey:#"type"]];
[last4Digits addObject:[cardDictionary objectForKey:#"last4Digits"]];
}];
There is a lot going on here, but I want to point one thing out.
Table data is being serialized to JSON.
NSMutableData *tableDataUpdated = [[NSJSONSerialization dataWithJSONObject:oldtableData
options:0
error:&error] copy];
Next, the data that was just serialized is de-serialized. It will always be the same array.
NSMutableDictionary *cardDictionary = [NSJSONSerialization JSONObjectWithData:tableDataUpdated options:0 error:NULL];
You will always get the same data back. You don't need to do the JSON step at all.

NSAarry to NSDictionary

I have an NSArray that looks like this
NSDictionary *dataDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(#"main: %#", [dataDict valueForKey:#"main"]);
main: [{"city": "dallas", "description": "this is my test description"}]
And I am trying to turn it into a NSDictionary so I get get element like [mainDict objectForKey#"city"]
So I tried this
NSLog(#"%#", [[mainArray objectAtIndex:0] objectForKey:#"city"]);
Thinking it would get the first element in mainArray and then the object that I want but I keep getting this error
[__NSCFString objectAtIndex:]: unrecognized selector sent to instance
How can I make the NSAarry into a NSDictionary?
Thanks
Create a for loop for list when you get response in [{},{}] format that means its a list of elements . Or you can ask your API developer to correct the error .
Any ways simple solution here is :
for (NSDictionary *d in [dataDict valueForKey:#"main"]){
NSlog (#"%#",d);
NSlog (#"%#",[d objectForKey :#"city"]);
}
Your error is saying mainarray is not a NSArray, it is NSString. So please check like this
NSDictionary *dataDict = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
NSLog(#"main: %#", [dataDict valueForKey:#"main"]);
if ([[dataDict valueForKey:#"main"] isKindOfClass:[NSArray class]]) {
NSArray *mainArray = [dataDict valueForKey:#"main"];
NSLog(#"City == %#",[[mainArray objectAtIndex:0] objectForKey:#"city"]);
}else{
NSLog(#"mainarray is kind of -> %#", NSClassFromString([dataDict valueForKey:#"main"]));
}
NSArray *mainArray = #[#{#"city":#"dallas", #"description":#"this is my test description"}];
NSLog(#"%#", [[mainArray objectAtIndex:0] objectForKey:#"city"]);
no problem ....

-[__NSCFArray objectForKey:]: unrecognized selector sent to instance 0x11c824e0

I face this error, Please help me for this and here is my code:
if(![[tmparr objectForKey:#"error"] isEqualToString:#"No data found"]){
resultArray = [NSArray arrayWithArray:[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]];}
The problem is that tmparr is a variable of type NSArray, but i guess you're treating it as an NSDictionary in this line:
[tmparr objectForKey:#"error"];
I solve this issue thanks to all
if( [tmparr isKindOfClass:[NSDictionary class]] && ![[tmparr objectForKey:#"error"] isEqualToString:#"No data found"]){
resultArray = [NSArray arrayWithArray:[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]];
}

NSJSONSerialization from an nsmanagedObject says a key is not key value coding-compliant

I'm trying to send back my NSManagedObject as a Serialized object to my webservice.
This is how I do it.
NSDictionary *menuDictionary = [self dictionaryFromMenu:appointment];
NSError *err;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:menuDictionary options:NSJSONWritingPrettyPrinted error:&err];
NSString *jsonString = [[NSString alloc] initWithData:jsonData
encoding:NSUTF8StringEncoding];
- (NSDictionary *)dictionaryFromMenu:(Appointment*)appointment {
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[appointment.app_id description],#"Id",
appointment.app_addressinfo, #"AddressInfo",
appointment.app_completed, #"Completed",
appointment.app_description, #"Description",
appointment.app_end, #"EndDate",
appointment.app_fullday, #"FullDay",
appointment.app_label, #"Label",
appointment.app_label_id, #"LabelId",
appointment.app_location, #"Location",
appointment.app_private, #"Private",
appointment.app_project_name, #"ProjectName",
appointment.app_project_number, #"ProjectNumber",
appointment.app_relation_address_city, #"RelationAddressCity",
appointment.app_relation_address_id, #"RelationAddressId",
appointment.app_relation_address_name, #"RelationAddressName",
appointment.app_relation_address_street, #"RelationAddressStreet",
appointment.app_relation_code, #"RelationCode",
appointment.app_relation_contact_id, #"RelationContactPersonId",
appointment.app_relation_contact_name, #"RelationContactPersonName",
appointment.app_relation_name, #"RelationName",
appointment.app_reminder_info, #"ReminderInfo",
appointment.app_start, #"StartDate",
appointment.app_state, #"State",
appointment.app_subject, #"Subject",
appointment.app_supplier_code, #"SupplierCode",
appointment.app_supplier_contact_person_id, #"SupplierContactPersonId",
appointment.app_supplier_contact_person_name, #"SupplierContactPersonName",
appointment.app_supplier_name, #"SupplierName",
appointment.app_type, #"Type",
nil];
return dict;
}
And this is how my entity looks like.
Now I get this error:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<Appointment 0x16dcb520> valueForUndefinedKey:]: the entity Appointment is not key value coding-compliant for the key "SupplierName".'
Any help ?
So the value for SupplierName is nil. That causes the construction of your dictionary to stop prematurely. You would have gotten a run time error if you had used the new #{}syntax.
You will need to change your code so for each key, if the value is nil, you use [NSNull null] instead.

Weird crash while accessing array objects at a given index in IOS

We have the following method where we are trying to access an array object at a given index. The array is resultArr. When we do a resultArr count it gives us a result of 13. So we know that the array is not null but when we try to do objectAtIndex it crashes with the error.
Function:
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData //1
options:kNilOptions
error:&error];
NSArray *keys = [json allKeys];
NSLog(#"keys: %#",keys);
NSArray* htmlAttributions = [json objectForKey:#"html_attributions"]; //2
NSArray* resultArr = (NSArray *)[json objectForKey:#"result"]; //2
NSArray* statusArr = [json objectForKey:#"status"]; //2
NSLog(#"htmlAttributions: %#",htmlAttributions);
NSLog(#"result: %#", resultArr); //3
NSLog(#"status: %#", statusArr); //3
NSLog(#"resultCount: %d",[resultArr count]);
[resultArr objectAtIndex:0];
}
Error:
2012-04-01 22:31:52.757 jsonParsing[5020:f803] resultCount: 13 2012-04-01 22:31:52.759 jsonParsing[5020:f803] -[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x6d2f900 2012-04-01 22:31:52.760 jsonParsing[5020:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance 0x6d2f900'
*** First throw call stack:
Thank you.
The error message is fairly descriptive. One of the objects that your code expects to be an NSArray is actually an NSDictionary. You cannot access fields inside of an NSDictionary by using NSArray methods (and casting from NSDictionary* to NSArray* will not convert an NSDictionary into an NSArray).
This would mean that inside of the JSON, one of your elements was serialized as an object/associative array instead of as a plain array. You can easily determine which one by looking at your JSON data as text, and finding the item that uses { and } instead of [ and ].
You are saying
NSArray* resultArr = (NSArray *)[json objectForKey:#"result"]; //2
But that does not make this object ([json objectForKey:#"result"]) an NSArray. It is an NSDictionary, and sending it a message that NSDictionary does not respond to (objectAtIndex:) causes a crash.
You were able to send it the count message without crashing because NSDictionary does happen to respond to the count message. But your preconception that this is an array is still mistaken.
You cannot cast an NSDictionary* to an NSArray* as you tried to do with this line: NSArray* resultArr = (NSArray *)[json objectForKey:#"result"];, then call -objectAtIndex.

Resources