数组中的多个项目会产生符合编码的错误

时间:2015-01-05 03:09:43

标签: ios objective-c arrays uitableview

我有一个自定义类,我通过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];
}

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

2 个答案:

答案 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获取数组。