数组中的多个项目给出符合编码的错误

Multiple items in array give coding-compliant error

我有一个自定义 class,我通过 NSUserDefaults 将数据存储在其中。当我将一个对象保存到数组中时,我可以轻松地将它读入我的 uitable 视图。它工作得很好。但是一旦数组中有超过 1 个对象,我就会收到以下错误:

 *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSConcreteMutableData 0x7f8adad3a630> valueForUndefinedKey:]: this class is not key value coding-compliant for the key fanLocation.'

我的 class 的代码如下:

#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

table 视图的代码是这样的

#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];
}

当我将它读取到视图时,我基本上尝试执行 "opposite" 保存它,但显然这不适用于多个值。知道要使此功能适用于用户默认值中的多个值的代码是什么吗?谢谢!

错误信息很清楚。您正在将 valueForKey: 发送到 NSData 对象。你不能那样做。

让我们看看您的代码,看看这是怎么回事。根据您自己的代码,您正在创建 unArchivedFavoritesList 作为 NSData 对象的 NSArray:

NSData *mfUnEndocedObject = 
    [NSKeyedUnarchiver unarchiveObjectWithData:mfavObject];
[unArchivedFavoritesList addObject:mfUnEndocedObject];

随后,您在该数组上调用 valueForKey:

[unArchivedFavoritesList valueForKey:@"fanLocation"];

valueForKey: 发送到 NSArray 发送 valueForKey: 到数组的每个包含的对象。但是 NSData 对象不响应 valueForKey:,所以这没有意义 - 我们崩溃了。

编辑:发生这种情况的原因原来是您在将对象放入数组之前对其进行了归档。这不是存档的工作方式。归档归档一个对象图。您使对象可存档,并将对象 自身 放入数组中。然后你归档数组!整个图——数组和对象——都为你存档了。现在你有一个可逆操作。

您必须编辑您的 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 取回数组。