我有一个自定义类,我通过NSUserDefaults存储数据。当我将一个对象保存到数组中时,我可以轻松地将其读取到我的 uitableview 中。它工作得很好。但是一旦数组中有超过 1 个对象,我就会收到以下错误:
*** 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"];
}
尝试读取收藏夹列表位置数组时发生错误。这是我保存到数组时的代码:
- (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];
}
当我将其读到视图时,我基本上尝试做保存它的"相反",但显然这不适用于多个值。知道使它适用于用户默认值中的多个值的代码是什么吗?谢谢!
错误消息非常清楚。您正在向 NSData 对象发送valueForKey:
。你不能这么做。
让我们看一下您的代码,看看这是如何发生的。根据您自己的代码,您正在创建 unArchivedFavoritesList
作为 NSData 对象的 NSArray:
NSData *mfUnEndocedObject =
[NSKeyedUnarchiver unarchiveObjectWithData:mfavObject];
[unArchivedFavoritesList addObject:mfUnEndocedObject];
随后,您将在该阵列上调用valueForKey:
:
[unArchivedFavoritesList valueForKey:@"fanLocation"];
发送到 NSArray valueForKey:
会将valueForKey:
发送到数组的每个包含对象。但是 NSData 对象不响应valueForKey:
,所以这毫无意义 - 我们崩溃了。
编辑:发生这种情况的原因是您在将对象放入数组之前对其进行存档。这不是归档的工作方式。存档存档对象图。您使对象可存档,并将对象本身放入数组中。然后你存档阵列!整个图形 - 数组和对象 - 为您存档。现在,您有一个可逆操作。
您必须编辑MotileFavored才能使用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
中取回数组。