3

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];
Erik
  • 2,500
  • 6
  • 28
  • 49

1 Answers1

1

MKMapItem does not conform to NSCoding or SSecureCoding.

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

zaph
  • 111,848
  • 21
  • 189
  • 228
  • can I convert it to NSData and if so - how? – Erik Jan 18 '15 at 12:13
  • as it doesn't conform to NSCoding, how can I encode each individual item? – Erik Jan 18 '15 at 12:16
  • That is basically what `NSCoding` does. – zaph Jan 18 '15 at 12:16
  • so I encode MKMapItem with NSKeyedArchiver and then also encode the whole custom object with NSKeyedArchiver as well? – Erik Jan 18 '15 at 12:17
  • `NSArchiver`, a concrete subclass of `NSCoder` so first you need to implement `NSCoder` which means `encodeWithCoder` and `initWithCoder`. Then you will have an `NSData` object. This is usually done so the `NSData` can be saved to a file. – zaph Jan 18 '15 at 12:22
  • see my update, that gives the same exception, only on that line. What am I doing wrong then? – Erik Jan 18 '15 at 12:24
  • are we talking to subclass MKMapItem and implement NSCoder that way? – Erik Jan 18 '15 at 12:36
  • what do you suggest is the best way? If I subclass it, I won't have to worry about it later and keep it in mind all the time – Erik Jan 18 '15 at 12:45
  • See: [MKMapItem+NSCoding.m](https://github.com/jstart/Terrific/blob/master/Terrific-Nearby/MKMapItem%2BNSCoding.m) on GitHub for an example. – zaph Jan 18 '15 at 12:45
  • is the MKMapItem subclass in this example "universal" so I can basically copy it or should it look different? – Erik Jan 18 '15 at 16:25
  • made it work now, but one more question; I see it's called MKMapItem+NSCoding.h, and I can't import it in my ViewControllers - does that mean it's automatically detected using "+NSCoding" in its file name? – Erik Jan 18 '15 at 16:48
  • "you should be a blue"? – Erik Jan 18 '15 at 18:20
  • You should be able to import it with that name but you can change the name. Oops, auto-correct strikes again! – zaph Jan 18 '15 at 18:23