我有一个自定义类,我通过NSUserDefaults存储数据。当我将一个对象保存到数组中时,我可以轻松地将其读入我的uitableview。它完美地运作。但是只要数组中有多个对象,我就会收到以下错误:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSConcreteMutableData 0x7f8adad3a630> valueForUndefinedKey:]: this class is not key value coding-compliant for the key fanLocation.'
我班级的代码如下:
#import <Foundation/Foundation.h>
@interface MotileFavorite : NSObject
@property (nonatomic, strong) NSString *favoriteName;
@property (nonatomic, strong) NSString *onNotificationsScreen;
@property (nonatomic, strong) NSString *fanLocation;
-(id)initWithName:(NSString *)favoriteName
withLocation:(NSString*)fanLocation
withIsOnNotificationsScreen:(NSString*)onNotificationsScreen;
@end
import "MotileFavorite.h"
@implementation MotileFavorite
-(id)initWithName:(NSString *)favoriteName withLocation:(NSString *)fanLocation withIsOnNotificationsScreen:(NSString *)onNotificationsScreen
{
self = [super init];
self.favoriteName = favoriteName;
self.fanLocation = fanLocation;
self.onNotificationsScreen = onNotificationsScreen;
return self;
}
- (void)encodeWithCoder:(NSCoder *)encoder {
//Encode properties, other class variables, etc
[encoder encodeObject:self.favoriteName forKey:@"favoriteName"];
[encoder encodeObject:self.fanLocation forKey:@"fanLocation"];
[encoder encodeObject:self.onNotificationsScreen forKey:@"onNotificationsScreen"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if((self = [super init])) {
//decode properties, other class vars
self.favoriteName = [decoder decodeObjectForKey:@"favoriteName"];
self.fanLocation = [decoder decodeObjectForKey:@"fanLocation"];
self.onNotificationsScreen = [decoder decodeObjectForKey:@"onNotificationsScreen"];
}
return self;
}
@end
表视图的代码是这个
#import <UIKit/UIKit.h>
@interface FavoritesListTableViewController : UITableViewController
@end
NSArray *favoritesArray;
NSArray *favoriteListNameArray;
NSArray *favoriteListLocationArray;
// .m viewDidLoad位于错误发生的位置
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.allowsMultipleSelectionDuringEditing = NO;
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults synchronize];
NSMutableArray *favoritesList = [defaults objectForKey:@"favoritesList"];
NSMutableArray *unArchivedFavoritesList = [NSMutableArray arrayWithCapacity:favoritesList.count];
for (NSData *mfavObject in favoritesList) {
NSData *mfUnEndocedObject = [NSKeyedUnarchiver unarchiveObjectWithData:mfavObject];
[unArchivedFavoritesList addObject:mfUnEndocedObject];
}
favoriteListLocationArray = [unArchivedFavoritesList valueForKey:@"fanLocation"];
favoriteListNameArray = [unArchivedFavoritesList valueForKey:@"favoriteName"];
}
尝试读取favoriteListLocationArray时发生错误。这是我保存到数组时的代码:
- (IBAction)savePressed:(id)sender {
if (_NotificationsSegmentedControl.selectedSegmentIndex == 0){
_notificationBool = @"Yes";
}
else{
_notificationBool = @"No";
}
MotileFavorite *favorite = [[MotileFavorite alloc] initWithName:_nameFavoriteTextField.text withLocation:@"FANLOCATION" withIsOnNotificationsScreen:_notificationBool];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *favoritesList = [[NSMutableArray alloc] initWithArray: [defaults objectForKey:@"favoritesList"]];
[favoritesList addObject:favorite];
NSMutableArray *archiveArray = [NSMutableArray arrayWithCapacity:favoritesList.count];
for (MotileFavorite *mfavObject in favoritesList) {
NSData *mfEndocedObject = [NSKeyedArchiver archivedDataWithRootObject:mfavObject];
[archiveArray addObject:mfEndocedObject];
}
[defaults setObject:archiveArray forKey:@"favoritesList"];
[defaults synchronize];
}
当我将它读取到视图时,我基本上尝试执行保存它的“相反”,但显然这不适用于多个值。知道代码是什么使这个用户默认值中的多个值?谢谢!
答案 0 :(得分:1)
错误信息非常清楚。您正在将valueForKey:
发送到NSData对象。你不能这样做。
让我们看看你的代码,看看它是如何发生的。根据您自己的代码,您正在创建unArchivedFavoritesList
作为NSData对象的NSArray:
NSData *mfUnEndocedObject =
[NSKeyedUnarchiver unarchiveObjectWithData:mfavObject];
[unArchivedFavoritesList addObject:mfUnEndocedObject];
随后,您在该阵列上调用valueForKey:
:
[unArchivedFavoritesList valueForKey:@"fanLocation"];
发送到NSArray的 valueForKey:
将valueForKey:
发送到每个数组包含的对象。但NSData对象不响应valueForKey:
,因此没有意义 - 我们崩溃了。
编辑:发生这种情况的原因是,在将对象放入数组之前,您正在归档对象。这不是归档的工作方式。归档归档对象图。您可以将对象设为可存档,并将对象自身放入数组中。然后归档阵列!整个图形 - 数组和对象 - 都是为您存档的。现在你有一个可逆的操作。
答案 1 :(得分:0)
您必须编辑MotileFavorite以使initWithCoder函数取消归档数据。
@implementation MotileFavorite
- (id)initWithCoder:(NSCoder *)coder;
{
if(self = [super init])
{
self.favoriteName = [coder decodeObjectForKey:@"favoriteName"];
self.fanLocation = [coder decodeObjectForKey:@"fanLocation"];
self.onNotificationsScreen = [coder decodeObjectForKey:@"fanLocation"];
}
return self;
}
@end
然后执行此操作以归档和取消归档。
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
MotileFavorite *m1 = [[MotileFavorite alloc] initWithName:@"A2"
withLocation:@"A"
withIsOnNotificationsScreen:@"A"];
MotileFavorite *m2= [[MotileFavorite alloc] initWithName:@"A1"
withLocation:@"A"
withIsOnNotificationsScreen:@"A"];
NSArray *array = [[NSArray alloc] initWithObjects:m1,m2, nil];
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver
archivedDataWithRootObject:array]
forKey:@"favoritesList"];
[defaults synchronize];
NSData *favouriteData = [defaults objectForKey:@"favoritesList"];
NSArray *unArchivedFavoritesList = [NSKeyedUnarchiver unarchiveObjectWithData:favouriteData];
favoriteListLocationArray = [unArchivedFavoritesList valueForKey:@"fanLocation"];
favoriteListNameArray = [unArchivedFavoritesList valueForKey:@"favoriteName"];
[NSKeyedArchiver archivedDataWithRootObject:]
从数组生成NSData对象。将其保存在NSUserDefaults中。
initWithCoder
执行encodeWithCoder函数的反向,以获取对象。
[NSKeyedUnarchiver unarchiveObjectWithData:]
从NSData
获取数组。