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];
Related
Hello i have a UIImageview and trying to set the image which was previously saved in a NSArray and then the NSArray is saved into an NSMutableDictionary. Here is the error and the code. Any help appreciated.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFConstantString _isSymbolImage]: unrecognized selector sent to instance 0x100e14318'
terminating with uncaught exception of type NSException
myAppDelegate *appDelegate = (myAppDelegate *)[UIApplication sharedApplication].delegate;
NSMutableArray *allKeys = [[appDelegate.localDataForIngestAndErrorVideos allKeys] mutableCopy];
for (NSString *key in allKeys) {
NSArray *object = (NSArray*)[appDelegate.localDataForIngestAndErrorVideos objectForKey:key];
NSLog(#"id object ingest: %#",[object objectAtIndex:0]);
if ( [cell.Model.ContentItem.videoUploadStatus isEqualToString:#"ingest"])
{
cell.Model.ContentItem.mediaVideoUriHls = (NSURL*)[object objectAtIndex:2];
UIImage *tempImage = [[UIImage alloc]init];
tempImage = [object objectAtIndex:1];
[cell.mediaImageView setImage:tempImage]; <=== here crashes
}
}
The error [__NSCFConstantString _isSymbolImage]: unrecognized selector sent to instance is saying this:
Let's translate first: __NSCFConstantString is a inner (optimized) class for NSString, so just consider it as NSString
So you have NSString instance and you try to call _isSymbolImage method on it. That method is hidden, it's an under the hood call from iOS SDK.
But that method doesn't exists on NSString, it doesn't know it, hence the error you are getting.
Seeing the crash line:
[cell.mediaImageView setImage:tempImage];
The inner method called makes sense, you are treating tempImage as it were an UIImage.
So [object objectAtIndex:1] is a NSString not a UIImage.
Now, I'd suggest to use custom model for your NSDictionary appDelegate.localDataForIngestAndErrorVideos. It's better than handling NSArray/NSDictionary without knowing what's inside it each time.
You could also add to it methods/compute properties like -(NSURL)ingestURL, etc to make your code easier and more readable.
Side note:
UIImage *tempImage = [[UIImage alloc]init];
tempImage = [object objectAtIndex:1];
The alloc/init is useless, since you are setting the value. You are doing an alloc/init for nothing, since you are ignoring it just after.
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];
I am saving JSON in NSUserDefaults. When I retrieve a NSArray, it's crashing for accessing one of my JSON keys and showing *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x174676fc0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key s.'
NSDictionary *status = [[NSUserDefaults standardUserDefaults] objectForKey:#”today”];
NSArray *ch = [status valueForKey:#"c"];
NSArray *service1 = [status valueForKey:#"s"];
NSArray *eventList = [status valueForKey:#"l"];
NSArray *time = [eventList valueForKey:#"s"];
NSArray *dur = [eventList valueForKey:#"d"];
NSArray *eveid = [eventList valueForKey:#"e"];
NSArray *title = [eventList valueForKey:#"t"];
It's crashing at 5 line of code.
TL;DR; You are getting an NSString back from NSUserDefaults, not the NSDictionary you expect.
Your exception:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x174676fc0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key s.'
Indicates that status is an instance of NSString, not NSDictionary.
This line:
NSDictionary *status = [[NSUserDefaults standardUserDefaults] objectForKey:#”today”];
Is returning an NSString. When you call -valueForKey: the receiver does not support that key, so it throws an NSUnknownKeyException exception. The solution here is to validate what you get from NSUserDefaults is what you expect.
Does it respond to -valueForKey:?
Does it support the key you are using?
Is it an NSDictionary?
Are you setting the NSUserDefaults value for today with a string elsewhere in your application when you meant to use a dictionary?
All of these things are worth checking.
You don't want to use valueForKey: in combination with JSON data. Instead, use objectForKey:, which is the NSDictionary method.
NSDictionary *status = [[NSUserDefaults standardUserDefaults] objectForKey:#"today"];
NSArray *ch = [status valueForKey:#"c"];
NSArray *service1 = [status valueForKey:#"s"];
Additionally, I propose you use the modern and shorter syntax:
NSDictionary *status = [[NSUserDefaults standardUserDefaults] objectForKey:#"today"];
NSArray *ch = status[#"c"];
NSArray *service1 = status[#"s"];
BTW.: Are all elements in status of type array? That's a bit surprising.
I basically get this error
'NSInvalidArgumentException', reason: '-[__NSCFConstantString objectForKey:]: unrecognized selector sent to instance 0x581f0'
on my program. I think it refers to this call I make,
if (data != nil) {
if([data objectForKey:#"username"]){
// NSArray *check= [[NSArray alloc]init];
//check=[data allValues];
[dict setObject:[data allValues] forKey:#"args"];
}else{
[dict setObject:[NSArray arrayWithObject:data] forKey:#"args"];
}
at the setObject:[data allValues]. I don't know why it gives that error but data is an NSDictionary and I'm getting all the values and placing it in an array.
Is the error happening here:
if([data objectForKey:#"username"]){
I assume so, as that is the only place objectForKey seems to be called. You are calling it on a variable called 'data', which i'm guessing simply is not a dictionary. You should NSLog its type to see.
In my app I am trying to store an array of MKPolylines into NSUserDefaults.
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:overlays];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:#"theKey"];
Gives:
[MKPolyline encodeWithCoder:]: unrecognized selector sent to instance 0x169c20`
Terminating app due to uncaught exception
'NSInvalidArgumentException', reason: '-
[MKPolyline encodeWithCoder:]: unrecognized
selector sent to instance 0x1c57e0'
Edit: I made some progress. MKPolylineView conforms to the NSCoding protocol, so I have converted my array of MKPolylines into an array of MKPolylineViews. The problem is that when I want to add them back to a map later, I can't convert them back to MKPolylines. Any idea how to do that?
Crashes at this code:
NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:#"theKey"];
NSArray* overlays = [NSKeyedUnarchiver unarchiveObjectWithData:data];
for(MKPolylineView* a in overlays)
[mapView addOverlay:a.overlay];
2011-10-17 21:15:56.416 Trail Tracker[4269:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(0x34b2f8bf 0x36c3a1e5 0x34a8420f 0x35697595 0x6257 0x62db 0x365f77ff 0x36601d53 0x36601cc1 0x366a1339 0x366a014f 0x366fad97 0x649b 0x36671565 0x366e9ce7 0x31fcc943 0x34b03a63 0x34b036c9 0x34b0229f 0x34a854dd 0x34a853a5 0x351f9fed 0x365ec743 0x2c75 0x2c34)
terminate called throwing an exception(gdb)
I am not pretty sure about this but the MKPolylines are made from the array of CLLocationCoordinate2D which contains float value for lat and long.
So if you can convert this array of CLLocationCoordinate2D into array of dictionary I think than you can save those lines in your user defaults.
You can do some thing like this
MKMapPoint *points = overlays.points;
NSMutableArray *temp = [NSMutableArray array];
for(int i = 0; i < points.length; i++)
{
// Not sure for this part
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:points[i].x], #"x", [NSNumber numberWithFloat:points[i].y], #"y", nil];
[temp addObject:dict];
}
Then you can use this array to store the overlay points in nsuserdefaults like this
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:temp];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:#"theKey"];
From looking at the inheritance hierarchy NSObject -> MKShape -> MKMultiPoint -> MKPolyline none of them conforms to NSCoding protocol. So, you can consider inheriting MKPolyline and include NSCoding protocol and implement the required method and use that.