Crashing with Terminating app due to uncaught exception 'NSUnknownKeyException - ios

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.

Related

iOS: can't set the null value in an NSMutableDictionary

I'm trying to set a value in an NSMutableDictionary but I'm always getting this error:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSDictionaryI 0x10fd55990> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key image.'
In the NSMutableDictionary I have an #"image" field that can be null. I want to replace the null value with a placeholder image name.
This is how I do it:
NSMutableDictionary * item = self.carouselSource[index];
if([Utils isNull:[item valueForKey:#"image"]]) {
[item setValue:#"default_image.png" forKey:#"image"];
}
But the application crash in this line
[item setValue:#"default_image.png" forKey:#"image"];
due to the error above.
Your dictionary is immutable - it's an NSDictionary and not an NSMutableDictionary.if you want to convert any(array, dictionary) immutable to mutable use mutableCopy for full conversion(balance the retain count).
NSMutableDictionary * item = [self.carouselSource[index] mutableCopy];
if([Utils isNull:[item objectForKey:#"image"]]) {
[item setObject:#"default_image.png" forKey:#"image"];
}
instead of
NSDictionary * item = self.carouselSource[index];
if([Utils isNull:[item valueForKey:#"image"]]) {
[item setValue:#"default_image.png" forKey:#"image"];
}

NSInvalidArgumentException', reason: '-[__NSArrayI length]: unrecognized selector sent to instance 0x165d5150'

Hi I am getting this data form server
NSDictionary*feed=[saveDic objectForKey:#"feed"];
NSLog(#"%#",feed); //Outputs: feed = ( { code = yQ7j0t; "user_id" = 889445341091863; } ); }
NSLog(#"%#",[feed valueForKey:#"code"]);
NSString *referralCode = [feed valueForKey:#"code"];
NSLog(#"%#",referralCode);
self.referralCode.text=referralCode;
And beacuse of that I am getting below error.
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI length]: selector sent to instance 0x165d5150'``
Any help will be appreciated.
The issue is, your feed key holds an array. You are not properly handling that in your code, that is why the crash occurs. When you call valueForKey: it retrieves an array of values held by that specific key.
For fixing that you can use:
NSArray *feed = [saveDic objectForKey:#"feed"];
NSArray *referralCodes = [feed valueForKey:#"code"];
NSString *referralCode = referralCodes.count ? referralCodes[0] : #"";
NSLog(#"%#",referralCode);
But I personally prefer using objectForKey: instead of valueForKey:. So you can re-write the code like:
NSArray *feed = [saveDic objectForKey:#"feed"];
NSString *referralCode = feed.count ? [feed[0] objectForKey:#"code"] : #"";
NSLog(#"%#",referralCode);
Some where you use a variable;
yourVaribleName.length
or
[yourVaribleName length]
which should be
yourVaribleName.count
note: the crash says exactly that "yourVaribleName" is NSArray type where you wants length of the NSArray. But NSArray has not feature "length". NSArray has "Count" feature
//try with this code bellow
NSArray *referralCode = [feed valueForKey:#"code"];
NSLog(#"%#",referralCode);
self.referralCode.text=[referralCode componentsJoinedByString:#" "];//#"," or #"" what event you need
Your feed data is in array. So you have retrieve code value from array.Hope it will help you.
NSMutableArray*feed=[saveDic objectForKey:#"feed"];
NSLog(#"%#",feed);
NSLog(#"%#",[feed valueForKey:#"code"]);
NSString *referralCode = [[feed objectAtIndex:indexPath]valueForKey:#"code"];
NSLog(#"%#",referralCode);
self.referralCode.text=referralCode;

Fetching data from PLIST by Fast Enumeration

I am using for in loop to fetch data from plist.For in loop is correct as it is printing value. But,suddenly, it is showing following exception:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectAtIndexedSubscript:]: unrecognized selector sent to instance 0x97a14b0'.
Code:
NSString *sss=[[NSBundle mainBundle]pathForResource:#"s" ofType:#"plist"];
NSDictionary *dic=[[NSDictionary alloc]initWithContentsOfFile:sss];
for(NSArray *arr in [dic allKeys])
{
NSLog(#"%#",arr); // Ii is printing value
NSLog(#"%#",arr[0]); // It is showing exceptions
}
Plist:
There is some problem with NSLog(#"%#",arr[0]);. I want to print values of first index of arrays a and b.
here [dic allKeys] will be keys in dic that are NSString like "a", "b" etc.
so for your plist the code should be,
NSString *sss=[[NSBundle mainBundle]pathForResource:#"s" ofType:#"plist"];
NSDictionary *dic=[[NSDictionary alloc]initWithContentsOfFile:sss];
for(NSString *key in [dic allKeys])
{
NSLog(#"%#",key);
NSArray *value = [dic objectForKey:key];
NSLog(#"%#",value[0]);
}

Removing an object from a mutable dictionary throws an exception

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

MKPolyline -> NSKeyedArchiver -> NSData SIGABRT

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.

Resources