This question already has answers here:
App Crashing: Mutating method sent to immutable object
(4 answers)
Closed 7 years ago.
I want to add an object to an existing NSMutableArray which already has data in it.
- (void)viewDidLoad {
[super viewDidLoad];
NSDictionary *json = [Server getMsgRecordwithfid:self.fid];
self.msgRecords = [[NSMutableArray alloc] init];
self.msgRecords = [json objectForKey:#"msg_record"];
}
- (IBAction)sendBtn:(id)sender {
NSDictionary *json = [Server insertNewMsg:data];
[self.msgRecords addObject:json];
}
When I run the above code, the program crashes at [self.msgRecords addObject:json];. And then it gives the below error message.
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'
What's wrong with my code?
What's wrong of my code?
Your code is writing over the NSMutableArray, replacing a mutable collection with an immutable one that you retrieve from json.
To fix this, call mutableCopy on the array that you retrieve:
// The first line is no longer necessary
//self.msgRecords = [[NSMutableArray alloc] init];
self.msgRecords = [[json objectForKey:#"msg_record"] mutableCopy];
Related
I have an NSMutableArray called myMutbaleArray that looks like this when I log it
2015-12-08 17:04:21.679 APP[3342:573379] (
{
id = 19;
"num_test" = 100000;
url = "http://fsad.com";
},
{
id = 20;
"num_test" = 100001;
url = "http://teeeet.com";
}
)
And I want to add an object that looks like this
{
id = 21;
"num" = 100002;
url = "http://example.com";
}
So I am trying this
[myMutbaleArray addObject:#{ #"id":#"23",#"num_test":#"100000", #"url":mainDict[#"website_url"],#"website_name":#"website"}];
But when I do this I get
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'
I initialize the array like this
#interface {
NSMutableArray *socailArray;
}
//inside connectionDidFinishLoading
socailArray = [dataDict valueForKey:#"socail"];
Why can I add another dictionary to the MutableArray?
Thanks
If you see this, your array is actually not a mutable array. Here is the hint:
-[__NSCFArray insertObject:atIndex:]
^^^^^^^^^^^
The object is of type __NSCFArray, which is an internal counterpart of NSArray.
Even if you declare your variable as NSMutableArray the pointer can point to an object of any type (event for example NSRegularExpression). Important is, how it is created.
This happens to most people if they serialise an array either using NSUserDefaults, NSJSONSerialization or what ever.
The key is to create a mutable copy when the array gets deserialised using
-[NSArray mutableCopy]
Note that this is not deep-copy. This means an array contained in the root array will not be mutable copied and needs to be replaced separately.
Deep copying can be achieved using this:
// array
NSArray *originalArray = #[#"a", #"b", #[#1, #2]];
NSMutableArray *mutableArray = (NSMutableArray *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFArrayRef)originalArray, kCFPropertyListMutableContainers);
// dictionary
NSDictionary *originalDictionary = #{#"a": #"b", #"c": #[#{#"abc": #123}]};
NSMutableDictionary *mutableDictionary = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)originalDictionary, kCFPropertyListMutableContainers);
You should change init to:
//inside connectionDidFinishLoading
socailArray = [NSMutableArray arrayWithArray:[dataDict valueForKey:#"socail"]];
Because: [dataDict valueForKey:#"socail"] is a NSArray.
With socailArray = [dataDict valueForKey:#"socail"];, the type of [dataDict valueForKey:#"socail"] is NSArray, so it auto cast socailArray into NSArray, that's why you can not insert thing into this.
To avoid this, you must be hold socailArray as NSMutableArray using:
socailArray = [[dataDict valueForKey:#"socail"] mutableCopy];
Hope this could help.
as the title says I'm having an issue with taking objects out of an array, flipping them, and putting them back in. Below is the code I currently have that ends in this error
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI removeObjectsAtIndexes:]: unrecognized selector sent to instance
I was wondering if anyone knew how to fix this? Here's a little more info on how I have it set up:
The object "PEG" is an NSString that displays "-0.6", "4.36"
GlobalSortedArray is an array filled with dictionary containing the PEG object
//Declare variables
NSMutableArray *negArray = [[NSMutableArray alloc]init];
NSMutableIndexSet *index = [[NSMutableIndexSet alloc]init];
int negcount = 0;
NSDictionary *forLoopDict;
for (forLoopDict in globalSortedArray)
{
if ([[forLoopDict objectForKey:#"PEG"] hasPrefix:#"-"])
{
[index addIndex:negcount];
}
negcount++;
}
NSLog(#"%#", negArray);
// Removes objects from main array. This is what seems to be messing up.
[globalSortedArray removeObjectsAtIndexes:index];
// Reverses the array
NSArray* reversedArray = [[negArray reverseObjectEnumerator] allObjects];
// insters them back into the main array
[globalSortedArray insertObjects:negArray atIndexes:0];
You are trying to remove an item from globalSortedArray. It is an NSArray and not mutable.
globalSortedArray as NSmutableArray
NSArray -- > NSMutableArray
This question already has answers here:
How to parse received response [closed]
(6 answers)
Closed 9 years ago.
I was trying to get the JSON data to an array. Below is the code... I dont know where am I going wrong..
When I keep a Log for arrayJSON Below is the result :
Array Result: [{"ID_PROJECT":1,"NM_PROJECT":"TED"},{"ID_PROJECT":2,"NM_PROJECT":"DL"},{"ID_PROJECT":3,"NM_PROJECT":"PERD"},{"ID_PROJECT":4,"NM_PROJECT":"EPRS "},{"ID_PROJECT":5,"NM_PROJECT":"MSCS"}]
NSArray *arrayJSON = [NSJSONSerialization JSONObjectWithData:urlData
options:NSJSONReadingAllowFragments
error:&error];
NSMutableArray *arrayResult = [NSMutableArray array];
for(NSDictionary *dictJSON in arrayJSON){
[arrayResult addObject: [dictJSON objectForKey:#"NM_PROJECT"]];
}
NSLog(#"Array Result: %#", arrayResult);
Here is the error code :
014-02-25 15:07:40.602 Demologin[1146:c07] * Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason:
'-[__NSCFString countByEnumeratingWithState:objects:count:]:
unrecognized selector sent to instance 0x715f430'
* First throw call stack: (0x1ca3012 0x114fe7e 0x1d2e4bd 0x1c92bbc 0x1c9294e 0xad28 0x1061c7 0x106232 0x553d5 0x5576f 0x55905 0x5e917
0x2296c 0x2394b 0x34cb5 0x35beb 0x27698 0x1bfedf9 0x1bfead0 0x1c18bf5
0x1c18962 0x1c49bb6 0x1c48f44 0x1c48e1b 0x2317a 0x24ffc 0x26ad 0x25d5)
libc++abi.dylib: terminate called throwing an exception
Array Result: [{"ID_PROJECT":1,"NM_PROJECT":"TED"},{"ID_PROJECT":2,"NM_PROJECT":"DL"},{"ID_PROJECT":3,"NM_PROJECT":"PERD"},{"ID_PROJECT":4,"NM_PROJECT":"EPRS "},{"ID_PROJECT":5,"NM_PROJECT":"MSCS"}]
NSMutableArray *array = [Array Result JSONValue];
[array retain];
NSLog(#"Array Result: %#", array);
This process is sending eMails, and it works fine, but the framework wants the body of the email to be an NSArray. So I try to convert the NSString to a NSDictionary to include with the NSArray here:
NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:kSKPSMTPPartContentTypeKey,
message,kSKPSMTPPartMessageKey,kSKPSMTPPartContentTransferEncodingKey, nil];
then I implement that here:
smtpTestMessage.parts = [NSArray arrayWithObject:plainPart];
Overall, here is my code:
NSLog(#"Start eMail");
SKPSMTPMessage *smtpTestMessage = [[SKPSMTPMessage alloc] init];
smtpTestMessage.fromEmail = #"***#gmail.com";
smtpTestMessage.toEmail = #"***#yahoo.com";
smtpTestMessage.relayHost = #"smtp.gmail.com";
smtpTestMessage.requiresAuth = YES;
smtpTestMessage.login = #"***#gmail.com";
smtpTestMessage.pass = #"***";
smtpTestMessage.subject = #"***";
smtpTestMessage.wantsSecure = YES;
smtpTestMessage.delegate = self;
NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:kSKPSMTPPartContentTypeKey,
message,kSKPSMTPPartMessageKey,kSKPSMTPPartContentTransferEncodingKey, nil];
smtpTestMessage.parts = [NSArray arrayWithObject:plainPart];
[NSString stringWithFormat:#"%#",message];
[smtpTestMessage send];
NSLog(#"sent");
But sadly enough, when I run the app, the eMail gets to the last stage... Then the app terminates saying
2013-10-15 00:43:50.512 BullyBox[3662:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'
*** First throw call stack:
(0x2f61ae8b 0x399156c7 0x2f5540cb 0x2f556749 0xc77f3 0x31dd555f 0x31dd54fb 0x31dd54cb 0x31dc10f3 0x31dd4f13 0x31dd4bdd 0x31dcfc09 0x31da4f59 0x31da3747 0x2f5e5f27 0x2f5e53ef 0x2f5e3bdf 0x2f54e541 0x2f54e323 0x342852eb 0x31e051e5 0xc91b5 0x39e0eab7)
libc++abi.dylib: terminating with uncaught exception of type NSException
EDIT
Now I keep getting the error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString appendString:]: nil argument'
Any help is greatly appreciated! Thank you for even reading this! xD <3
Make sure plainPart is created successfully and not a nil.
It's tough to judge but if I had to guess plainPart is not getting created. Why do I think this? Let's take a look at the error:
[__NSPlaceholderArray initWithObjects:count:]:
This points to an alloc/init sequence of calls. The only place in the code you shared where you are allocating an array is here:
smtpTestMessage.parts = [NSArray arrayWithObject:plainPart];
Therefore, if you are trying to create an array with a nil object, plainPart, then it makes sense why you are getting an error about trying to insert a nil object at location 0.
Try setting a breakpoint right at this call in your code. This will help you narrow down where the crash happens.
I am not sure what you are trying to do here
NSDictionary *plainPart = [NSDictionary dictionaryWithObjectsAndKeys:kSKPSMTPPartContentTypeKey,
message,kSKPSMTPPartMessageKey,kSKPSMTPPartContentTransferEncodingKey, nil];
but based on you naming convention you are storing a key in a value location. Also you could switch to the modern objective-C syntax
NSDictionary *plainPart = #{
message: kSKPSMTPPartContentTypeKey,
kSKPSMTPPartContentTransferEncodingKey: kSKPSMTPPartMessageKey
};
This is equivalent to what you wrote, but more readable. As stated in the other answers it look like there is a problem with the creation of plainPart. Hopefully looking at this should make it easier to debug.
Check first this line smtpTestMessage.parts = [NSArray arrayWithObject:plainPart];.
Whether it is smtpTestMessageallocated if yes then check any data exist inside this or not
I'm getting an exception after attempting to remove an object from a NSMutableDictionary. The relevant code follows. The 'settings' is passed to the method and can be a NSDictionary or a NSMutableDictionary.
NSMutableDictionary *mutableSettings = nil;
if ([settings isKindOfClass:[NSMutableDictionary class]])
mutableSettings = (NSMutableDictionary *)settings;
else
mutableSettings = [[[NSMutableDictionary alloc] initWithDictionary:settings] autorelease];
[mutableSettings removeObjectForKey:#"akey"];
This crashes with
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary removeObjectForKey:]: mutating method sent to immutable object'
Whats wrong with this? Thanks.
The problem here is that both NSDictionary and NSMutableDictionary return __NSCFDictionary as their class, due to the fact that NSDictionary is a class cluster.
I think you will just have to make a mutable copy of the settings dictionary whether it is mutable or not.
NSMutableDictionary *mutableSettings = [settings mutableCopy];