在NSUserDefaults中将自定义对象存储在NSMutableArray中
我最近一直试图将我的iPhone应用程序的搜索结果存储在NSUserDefaults集合中。我也使用它来成功保存用户注册信息,但由于某种原因,试图存储自定义位置类的NSMutableArray始终为空。在NSUserDefaults中将自定义对象存储在NSMutableArray中
我试图转换的NSMutableArray到NSData的元素作为这个帖子的,但我得到了相同的结果(Possible to save an integer array using NSUserDefaults on iPhone?)
我已经尝试了代码示例:
节省:
[prefs setObject:results forKey:@"lastResults"];
[prefs synchronize];
或
NSData *data = [NSData dataWithBytes:&results length:sizeof(results)];
[prefs setObject:data forKey:@"lastResults"];
或
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:results];
[prefs setObject:data forKey:@"lastResults"];
负载:
lastResults = (NSMutableArray *)[prefs objectForKey:@"lastResults"];
或
NSData *data = [prefs objectForKey:@"lastResults"];
memcpy(&lastResults, data.bytes, data.length);
或
NSData *data = [prefs objectForKey:@"lastResults"];
lastResults = [NSKeyedUnarchiver unarchiveObjectWithData:data];
经过以下建议下面我也implemente d NSCoder在我对象(忽略的NSString其临时的过度使用):
#import "Location.h"
@implementation Location
@synthesize locationId;
@synthesize companyName;
@synthesize addressLine1;
@synthesize addressLine2;
@synthesize city;
@synthesize postcode;
@synthesize telephoneNumber;
@synthesize description;
@synthesize rating;
@synthesize priceGuide;
@synthesize latitude;
@synthesize longitude;
@synthesize userLatitude;
@synthesize userLongitude;
@synthesize searchType;
@synthesize searchId;
@synthesize distance;
@synthesize applicationProviderId;
@synthesize contentProviderId;
- (id) initWithCoder: (NSCoder *)coder
{
if (self = [super init])
{
self.locationId = [coder decodeObjectForKey:@"locationId"];
self.companyName = [coder decodeObjectForKey:@"companyName"];
self.addressLine1 = [coder decodeObjectForKey:@"addressLine1"];
self.addressLine2 = [coder decodeObjectForKey:@"addressLine2"];
self.city = [coder decodeObjectForKey:@"city"];
self.postcode = [coder decodeObjectForKey:@"postcode"];
self.telephoneNumber = [coder decodeObjectForKey:@"telephoneNumber"];
self.description = [coder decodeObjectForKey:@"description"];
self.rating = [coder decodeObjectForKey:@"rating"];
self.priceGuide = [coder decodeObjectForKey:@"priceGuide"];
self.latitude = [coder decodeObjectForKey:@"latitude"];
self.longitude = [coder decodeObjectForKey:@"longitude"];
self.userLatitude = [coder decodeObjectForKey:@"userLatitude"];
self.userLongitude = [coder decodeObjectForKey:@"userLongitude"];
self.searchType = [coder decodeObjectForKey:@"searchType"];
self.searchId = [coder decodeObjectForKey:@"searchId"];
self.distance = [coder decodeObjectForKey:@"distance"];
self.applicationProviderId = [coder decodeObjectForKey:@"applicationProviderId"];
self.contentProviderId = [coder decodeObjectForKey:@"contentProviderId"];
}
}
- (void) encodeWithCoder: (NSCoder *)coder
{
[coder encodeObject:locationId forKey:@"locationId"];
[coder encodeObject:companyName forKey:@"companyName"];
[coder encodeObject:addressLine1 forKey:@"addressLine1"];
[coder encodeObject:addressLine2 forKey:@"addressLine2"];
[coder encodeObject:city forKey:@"city"];
[coder encodeObject:postcode forKey:@"postcode"];
[coder encodeObject:telephoneNumber forKey:@"telephoneNumber"];
[coder encodeObject:description forKey:@"description"];
[coder encodeObject:rating forKey:@"rating"];
[coder encodeObject:priceGuide forKey:@"priceGuide"];
[coder encodeObject:latitude forKey:@"latitude"];
[coder encodeObject:longitude forKey:@"longitude"];
[coder encodeObject:userLatitude forKey:@"userLatitude"];
[coder encodeObject:userLongitude forKey:@"userLongitude"];
[coder encodeObject:searchType forKey:@"searchType"];
[coder encodeObject:searchId forKey:@"searchId"];
[coder encodeObject:distance forKey:@"distance"];
[coder encodeObject:applicationProviderId forKey:@"applicationProviderId"];
[coder encodeObject:contentProviderId forKey:@"contentProviderId"];
}
对于阵列中加载自定义对象,这是我用抢的数组:
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedArray"];
if (dataRepresentingSavedArray != nil)
{
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
if (oldSavedArray != nil)
objectArray = [[NSMutableArray alloc] initWithArray:oldSavedArray];
else
objectArray = [[NSMutableArray alloc] init];
}
您应该检查从用户默认返回的数据不为零,因为我相信解除封存从零导致崩溃。
存档很简单,使用下面的代码:
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:objectArray] forKey:@"savedArray"];
由于f3lix指出的那样,你需要使你的自定义对象均符合欧盟的NSCoding协议。像下面添加方法应该做的伎俩:
- (void)encodeWithCoder:(NSCoder *)coder;
{
[coder encodeObject:label forKey:@"label"];
[coder encodeInteger:numberID forKey:@"numberID"];
}
- (id)initWithCoder:(NSCoder *)coder;
{
self = [super init];
if (self != nil)
{
label = [[coder decodeObjectForKey:@"label"] retain];
numberID = [[coder decodeIntegerForKey:@"numberID"] retain];
}
return self;
}
请参阅“NSUserDefaults的为什么没能挽救的NSMutableDictionary在iPhone SDK? “(Why NSUserDefaults failed to save NSMutableDictionary in iPhone SDK?)
如果你想(反)序列化的自定义对象,你必须提供的功能(反)序列化的数据(NSCoding协议)。该解决方案你是指与INT作品数组,因为数组是不是对象,而是一个连续的内存块。
我认为您的权利,我会看看到NSCoding(除非你有一个建议linky),本身是由上NSString的对象是所有的,所以我想我可以写我自己的串行器,并把它们全部放入一个字符串数组 – 2009-02-11 14:56:07
好吧,所以我已经实现了NSCode,但仍然没有使用NSArchiver – 2009-02-11 16:29:53
我认为它看起来像你的代码不保存结果阵列的问题。它的加载数据尝试使用
lastResults = [prefs arrayForKey:@"lastResults"];
这将返回数组s通过钥匙特化。
我会建议不要试图在默认数据库中存储这样的东西。
SQLite很容易拾取和使用。我在我的一个屏幕录像(http://pragprog.com/screencasts/v-bdiphone)中插入了一段关于我写的简单包装(您可以在不购买SC的情况下获得代码)。
在应用程序空间中存储应用程序数据要干净得多。
所有这一切说,如果它仍然是有道理的把这个数据放入默认的数据库,然后看到帖子f3lix张贴。
谢谢你的建议,但我真的不想开始编写SQL查询我在你的例子中看到)只是为了一个有几个字符串的对象 – 2009-02-11 16:58:39
我想你已经在你的initWithCoder方法得到一个错误,至少在所提供的代码,你不回的“自我”的对象。
- (id) initWithCoder: (NSCoder *)coder
{
if (self = [super init])
{
self.locationId = [coder decodeObjectForKey:@"locationId"];
self.companyName = [coder decodeObjectForKey:@"companyName"];
self.addressLine1 = [coder decodeObjectForKey:@"addressLine1"];
self.addressLine2 = [coder decodeObjectForKey:@"addressLine2"];
self.city = [coder decodeObjectForKey:@"city"];
self.postcode = [coder decodeObjectForKey:@"postcode"];
self.telephoneNumber = [coder decodeObjectForKey:@"telephoneNumber"];
self.description = [coder decodeObjectForKey:@"description"];
self.rating = [coder decodeObjectForKey:@"rating"];
self.priceGuide = [coder decodeObjectForKey:@"priceGuide"];
self.latitude = [coder decodeObjectForKey:@"latitude"];
self.longitude = [coder decodeObjectForKey:@"longitude"];
self.userLatitude = [coder decodeObjectForKey:@"userLatitude"];
self.userLongitude = [coder decodeObjectForKey:@"userLongitude"];
self.searchType = [coder decodeObjectForKey:@"searchType"];
self.searchId = [coder decodeObjectForKey:@"searchId"];
self.distance = [coder decodeObjectForKey:@"distance"];
self.applicationProviderId = [coder decodeObjectForKey:@"applicationProviderId"];
self.contentProviderId = [coder decodeObjectForKey:@"contentProviderId"];
}
return self; // this is missing in the example above
}
我用
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:results];
[prefs setObject:data forKey:@"lastResults"];
和
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"lastResults"];
if (dataRepresentingSavedArray != nil)
{
NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray];
if (oldSavedArray != nil)
objectArray = [[NSMutableArray alloc] initWithArray:oldSavedArray];
else
objectArray = [[NSMutableArray alloc] init];
}
和它的工作非常适合我。
与问候,
斯特凡
我已经将你的代码和实现NSCoder的对象复制到原型中,但是desp ite来自UserDefaults的NSData有数据,最终数组仍然有0的计数。任何想法?我会尝试将我的原型上传到某处 – 2009-02-13 16:31:50