I'm saving a customized class DeviceInfo
in to NSDefault.
I already used NSKeyedArchiver
to archive the object into a NSData
object.
As I want to save an array of deviceInfo
objects into NSUserDefault
, I put the archived objects into an NSArray
.
However, it seems that, when there's only one NSData
object in the array, I always get an NSData
object while it should be an NSArray
object when I fetch it from NSUserDefault
.
Why is that?
Here's the code.
NSData* data = [NSKeyedArchiver archivedDataWithRootObject:_deviceInfo];
NSMutableArray *temp = [NSMutableArray new];
temp = [[SDGridItemCacheTool itemsArray] mutableCopy]; //[[SDGridItemCacheTool itemsArray]] is the method the fetch the array, I paste the code below.
[temp addObject:data];
[SDGridItemCacheTool saveItemsArray:[temp copy]];
And the code to save and fetch data from NSUserDefault
//SDGridItemCacheTool.m
+ (NSArray *)itemsArray
{
return [[NSUserDefaults standardUserDefaults] objectForKey:kItemsArrayCacheKey];
}
+ (void)saveItemsArray:(NSArray *)array
{
[[NSUserDefaults standardUserDefaults] setObject:[array copy] forKey:kItemsArrayCacheKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
Finally the DeviceInfo
class:
@interface DeviceInfo : NSObject <NSCoding>
@property (nonatomic, retain) NSString* title;
@property (nonatomic, retain) NSString* imageResString;
@property (nonatomic, retain) NSNumber* currentStat;
@property (nonatomic, retain) NSDictionary* colorStatPair;
@end
@implementation DeviceInfo
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
if (self = [super init]) {
_title = [aDecoder decodeObjectForKey:kUserDefaultDeviceTitleKey];
_imageResString = [aDecoder decodeObjectForKey:kUserDefaultDeviceImageResStringKey];
_currentStat = [aDecoder decodeObjectForKey:KUserDefaultDeviceCurrentStatKey];
_colorStatPair = [aDecoder decodeObjectForKey:kUserDefaultDeviceColorStatPair];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_title forKey:kUserDefaultDeviceTitleKey];
[aCoder encodeObject:_imageResString forKey:kUserDefaultDeviceImageResStringKey];
[aCoder encodeObject:_currentStat forKey:KUserDefaultDeviceCurrentStatKey];
[aCoder encodeObject:_colorStatPair forKey:kUserDefaultDeviceColorStatPair];
}
@end
There are a few issues with your code.
Your itemsArray
method will return nil
until you actually save some data. So you need to handle that properly. Your saveItemsArray:
method needlessly does a copy of the array and it needlessly calls synchronize
.
Updated SDGridItemCacheTool.m
+ (NSArray *)itemsArray
{
NSArray *result = [[NSUserDefaults standardUserDefaults] objectForKey:kItemsArrayCacheKey];
if (!result) {
result = [NSArray array];
}
return result;
}
+ (void)saveItemsArray:(NSArray *)array
{
[[NSUserDefaults standardUserDefaults] setObject:array forKey:kItemsArrayCacheKey];
}
And your code that calls these two methods needs some cleanup.
NSData* data = [NSKeyedArchiver archivedDataWithRootObject:_deviceInfo];
NSMutableArray *temp = [[SDGridItemCacheTool itemsArray] mutableCopy];
[temp addObject:data];
[SDGridItemCacheTool saveItemsArray:temp];
There was no need to create an NSMutableArray
and then replace it. And there's no need to copy the array.
You may also wish to delete and reinstall your app to start with clean user defaults. If you have changed this code a bit, you may have a non-array stored in that key from earlier code.