Search code examples
iosobjective-csingletonnsobjectnskeyedarchiver

Encoding and decoding custom objects


I'm having trouble encoding and saving a list of custom objects containing a MKMapItem to NSUserDefaults.

Firstly, I get the selected MKMapItem from an array of MKMapItems used for a tableView and store that in my sharedManager instance. (All the values in sharedManager will be used later to create a custom object).

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

// Get the tapped MKMapItem
MKMapItem *selectedMapItem = self.searchResults[indexPath.row];

// Create a sharedManager instance
MyManager *sharedManager = [MyManager sharedManager];

// Set the workRegion and workLocation in sharedManager
NSLog(@"selectedMapItem: %@", [selectedMapItem name]);
sharedManager.workLocation = selectedMapItem;

// Post a notification to alert the PreviewMapViewController
[[NSNotificationCenter defaultCenter] postNotificationName:@"showAnnotations" object:self.searchResults];
[[NSNotificationCenter defaultCenter] postNotificationName:@"zoomToAnnotation" object:selectedMapItem];
[[NSNotificationCenter defaultCenter] postNotificationName:@"showMap" object:nil];
}

enter image description here enter image description here

This is the code I use to take the MKMapItem from sharedManager and put it in the custom object I've created:

MyManager *sharedManager = [MyManager sharedManager];
newModel.workLocation = sharedManager.workLocation;

My custom object stores workLocation in its header file with a property as follows:

@property (nonatomic, strong) MKMapItem *workLocation;

This is the implementation file where I encode and decode the workLocation object:

@implementation WorkLocationModel

-(id)init {
// Init self
self = [super init];
if (self)
{
    // Setup
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.workLocation forKey:@"workLocation"];
}

-(instancetype)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self)
self.workLocation = [coder decodeObjectForKey:@"workLocation"];
return self;
}

@end

enter image description here

My breakpoint set to catch all the exceptions breaks on the encodeObject line.

The error occurs when I add this custom object to a NSMutableArray and then save that array using:

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:_myObjects] forKey:@"myObjects"];

Exception: -[MKMapItem encodeWithCoder:]: unrecognized selector sent to instance 0x7f9f14acf400

Can anyone help me with this?

UPDATE:

NSData *workLocationData = [NSKeyedArchiver archivedDataWithRootObject:sharedManager.workLocation];

Solution

  • MKMapItem does not conform to NSCoding or SSecureCoding.

    You will need to encode the individual items and re-create a MKMapItem on decode.