In my app, I'm reading and writing an NSMutableArray to NSUserDefaults. This array contains objects that look like this:
header file:
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
@interface WorkLocationModel : NSObject
@property (nonatomic, strong) CLRegion *geoLocation;
@end
implementation file:
#import "WorkLocationModel.h"
@implementation WorkLocationModel
-(id)init {
// Init self
self = [super init];
if (self)
{
// Setup
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.geoLocation forKey:@"geoLocation"];
}
-(void)initWithCoder:(NSCoder *)coder {
self.geoLocation = [coder decodeObjectForKey:@"geoLocation"];
}
@end
This is how I read my list:
This is in the ViewController where I load the array, oldArray seems to log 1 item (correct amount) of the type NSKeyedUnarchiver when it's supposed to be a WorkLocationModel object:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *workLocationsData = [defaults objectForKey:@"workLocations"];
if (workLocationsData != nil)
{
NSArray *oldArray = [NSKeyedUnarchiver unarchiveObjectWithData:workLocationsData];
if (oldArray != nil)
{
_workLocations = [[NSMutableArray alloc] initWithArray:oldArray];
NSLog(@"Not nil, count: %lu", (unsigned long)_workLocations.count);
} else
{
_workLocations = [[NSMutableArray alloc] init];
}
} else
{
_workLocations = [[NSMutableArray alloc] init];
}
This is how I add the WorkLocationModel objects to my array:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Create a sample work location
WorkLocationModel *newModel = [[WorkLocationModel alloc] init];
newModel.geoLocation = currentRegion;
[_workLocations addObject:newModel];
// Save the new objects
[defaults setObject:[NSKeyedArchiver archivedDataWithRootObject:_workLocations] forKey:@"workLocations"];
// Synchronize the defaults
[defaults synchronize];
The error occurs on the if-statement here (further down into my ViewController), where I'm comparing two CLRegions.
region is a function argument.
for (WorkLocationModel *currentWorkLocationModel in _workLocations)
{
if ([region isEqual:currentWorkLocationModel.geoLocation])
{
// Found a match
}
}
I've gone through the code but I don't understand why this is happening, exception message:
-[NSKeyedUnarchiver geoLocation]: unrecognized selector sent to instance 0x174108430
2015-01-12 18:23:20.085 myApp[1322:224462] *** Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason: '-[NSKeyedUnarchiver geoLocation]:
unrecognized selector sent to instance
Can someone help me with this? I'm lost
The initWithCoder:
method is just like any other init method - it must call super
and return an instance. Your method should be:
- (instancetype) initWithCoder:(NSCoder *)coder
{
self = [super init];
if(self)
self.geoLocation = [coder decodeObjectForKey:@"geoLocation"];
return self;
}
If your superclass implements initWithCoder:
as well the super
call would be [super initWithCoder:coder]
(and similarly for encodeWithCoder:
) - NSObject
does not so you are OK in both your encoding and decoding.
A breakpoint on your encode, decode and reading methods would have quickly narrowed your problem down for you.
HTH