xcode 使用 NSUserDefaults 保存 NSMutableArray 不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10444131/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Saving a NSMutableArray using NSUserDefaults not working
提问by Grauzten
I have this mutable array named myWallet with its property declaration:
我有一个名为 myWallet 的可变数组及其属性声明:
@property (nonatomic, strong) NSMutableArray *myWallet;
This array is being filled up by Cards, which is an object. I create a new instance of a Card from another View Controller so I use a delegate method in able to pass this created card on my initial View Controller which is a Table View Controller. Below is the delegate method
这个数组被 Cards 填充,它是一个对象。我从另一个视图控制器创建了一个卡片的新实例,所以我使用委托方法能够在我的初始视图控制器(表视图控制器)上传递这个创建的卡片。下面是委托方法
- (void)addCardViewController:(AddCardViewController *)sender didCreateCard:(Card *)newCard
{
// insert a new card
self.myCard = newCard;
[self.myWallet addObject:self.myCard];
[self.tableView reloadData];
}
So far, I can create new instances of Card, and when I do, a new table cell appears in my initial view controller (Card Wallet VC).
到目前为止,我可以创建 Card 的新实例,当我这样做时,一个新的表格单元格会出现在我的初始视图控制器 (Card Wallet VC) 中。
What I want is when the user is done using the app, the created instance(s) of Card he / she previously created still appears on next run time of the app. So I used NSUserDefaults to do this. The method below is how I'm using NSUserDefaults to save.
我想要的是当用户完成使用应用程序时,他/她之前创建的 Card 创建实例仍然出现在应用程序的下一次运行时。所以我使用 NSUserDefaults 来做到这一点。下面的方法是我如何使用 NSUserDefaults 进行保存。
- (void)saveMyWallet
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.myWallet forKey:@"myWalletArray"];
[defaults synchronize];
NSLog(@"I am saved");
}
I call this method inside the didSelectRowAtIndexPath. When I run the app, then create a new instance of a Card, click the table cell, this appears on my log.
我在 didSelectRowAtIndexPath 中调用了这个方法。当我运行应用程序时,然后创建一个 Card 的新实例,单击表格单元格,这会出现在我的日志中。
2012-05-04 14:51:00.900 CardWallet[24998:f803] *** -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '("<Card: 0x6aa02f0>")' of class '__NSArrayM'.
Note that dictionaries and arrays in property lists must also contain only property values.
What could be a possible reason to this? And can you suggest me ways I can go about it.
这可能是什么原因?你能不能给我建议我可以做的事情。
Thanks in advance.
提前致谢。
回答by Jonas Schnelli
Your Card class must also conform to the NSCoding Protocolbecause you can only store NSData
, NSString
, NSArray
, NSDictionary
and NSNumber
with NSUserDefaults
.
That means, you need to add two methods to your class:
你的卡类也必须符合NSCoding协议,因为你只能存储NSData
,NSString
,NSArray
,NSDictionary
并NSNumber
用NSUserDefaults
。这意味着,您需要向类中添加两个方法:
- (void)encodeWithCoder:(NSCoder *)enCoder {
[super encodeWithCoder:enCoder];
[enCoder encodeObject:instanceVariable forKey:INSTANCEVARIABLE_KEY];
// Similarly for the other instance variables.
....
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if(self = [super initWithCoder:aDecoder]) {
self.instanceVariable = [aDecoder decodeObjectForKey:INSTANCEVARIABLE_KEY];
// similarly for other instance variables
....
}
return self;
}
Then create a NSData NSKeyedArchiver before storing it to NSUserDefaults. Like this:
然后在将其存储到 NSUserDefaults 之前创建一个 NSData NSKeyedArchiver。像这样:
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
NSData *yourArrayAsData = [NSKeyedArchiver archivedDataWithRootObject:yourArray];
[ud setObject:sharesAsData forKey:kA_KEY_FOR_USERDEFAULTS];
回答by Janak Nirmal
@implementation Card
- (void)encodeWithCoder:(NSCoder *)enCoder
{
[super encodeWithCoder:enCoder];
[enCoder encodeObject:self.name forKey:@"CardName"];
[enCoder encodeInt:self.pin forKey:@"CardPin"];
[enCoder encodeDouble:self.points forKey:@"CardPoints"];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
if(self = [super initWithCoder:aDecoder])
{
self.name = [aDecoder decodeObjectForKey:@"CardName"];
self.pin = [aDecoder decodeIntForKey:@"CardPin"];
self.points = [aDecoder decodeDoubleForKey:@"CardPoints"];
}
return self;
}
@end
Assumed that name is of type NSString, pin is of type NSInteger and Points is of type Double you can use above code directly in your project.
假设 name 是 NSString 类型,pin 是 NSInteger 类型,Points 是 Double 类型,你可以直接在你的项目中使用上面的代码。