MKPolyline -> NSKeyedArchiver -> NSData SIGABRT - ios

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.

Related

Fatal error when setting UIImageView in objective c

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.

How to store my customer NSMutableArray in NSUserDefaults for Objective-C?

I am trying to store my customer data into NSUserDefaults. The customer data is like the following:
AvinLightInfo.h
#import <Foundation/Foundation.h>
#interface AvinLightInfo : NSObject
#property (nonatomic)uint16_t Address;
#property (strong,nonatomic)NSString* name;
#property (strong,nonatomic)NSMutableArray* ColorTempInfo;
#property (strong,nonatomic)NSMutableArray* BrightnessInfo;
#end
In view.m
NSMutableArray *AvinLightDataBase = [[NSMutableArray alloc] init];
AvinLightInfo *Avinlightinfo = [[AvinLightInfo alloc] init];
Avinlightinfo.Address = CFSwapInt16(0x3711);
Avinlightinfo.name = #"TEST";
Avinlightinfo.ColorTempInfo = [[NSMutableArray alloc] init];
Avinlightinfo.BrightnessInfo = [[NSMutableArray alloc] init];
NSNumber* defaultValue = [NSNumber numberWithInt:200];
for(int j = 0 ; j < 4 ; j++){
[Avinlightinfo.ColorTempInfo addObject:defaultValue];
[Avinlightinfo.BrightnessInfo addObject:defaultValue];
}
[AvinLightDataBase addObject:Avinlightinfo];
I try to use the following code to store the above data in NSUserDefaults.
[[NSUserDefaults standardUserDefaults] setObject:AvinLightDataBase forKey:#"AvinLightDataBase"];
[[NSUserDefaults standardUserDefaults] synchronize];
But it crash and show the following error log:
2016-12-27 16:35:23.491723 MESH[2458:992363] [User Defaults] Attempt to set a non-property-list object (
"<AvinLightInfo: 0x1702414a0>"
) as an NSUserDefaults/CFPreferences value for key AvinLightDataBase
2016-12-27 16:35:23.492929 MESH[2458:992363] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object (
"<AvinLightInfo: 0x1702414a0>"
) for key AvinLightDataBase'
How to store my customer NSMutableArray in NSUserDefaults for Objective-C ?
-------------------------EDIT-------------------------------
I also try the following method:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:AvinLightDataBase];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:data forKey:#"light"];
[defaults synchronize];
But it crash and the error log is :
-[AvinLightInfo encodeWithCoder:]: unrecognized selector sent to instance 0x17405c8c0
2016-12-27 17:20:54.203510 MESH[2481:998134] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[AvinLightInfo encodeWithCoder:]: unrecognized selector sent to instance 0x17405c8c0'
*** First throw call stack:
You can store an array of custom object by the following way
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:yourArray];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:data forKey:#"yourKey"];
NSArray *array= [NSKeyedUnarchiver unarchiveObjectWithData:[defaults objectForKey:#"yourKey"];
For more detail you can follow this tutorial Archiving Objective-C Objects with NSCoding
NSUserDefault can only support NSNumber(NSInteger、float、double),NSString,NSDate,NSArray,NSDictionary,BOOL,
So, if you want to store customer data, you should convert you customer data to NSData, and your customer object must be implement NSCoding, and override encodeWithCoder and initWithCoder.
And then, please pay attention to your code style, the variable will be start with lower case.
Use this Third party RMMApper
To store use
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults rm_setCustomObject:AvinLightDataBase forKey:#"key"];
To retrive
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *object = [defaults rm_customObjectForKey:#"key"];

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;

Crashing with Terminating app due to uncaught exception 'NSUnknownKeyException

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.

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

Resources