NSUserdefaults 不适用于 NSKeyedArchiver

NSUserdefaults not working with NSKeyedArchiver

我有一个 NSMutableArray,里面装满了我的电影 class 的对象,我想保存它,但它不起作用,我不明白为什么...

Movie.h:

@interface Movie : NSObject <NSCoding>{
    NSString *name;
    int year;
    int length;
    NSString *file_size;
    int rating;
    NSArray *genre;
    NSString *plot;
}

@property (nonatomic, retain) NSString *name;
@property (nonatomic, assign) int year;
@property (nonatomic, assign) int length;
@property (nonatomic, retain, retain) NSString *file_size;
@property (nonatomic, assign) int rating;
@property (nonatomic, retain) NSArray *genre;
@property (nonatomic, retain) NSString *plot;

-(id) initWithName:(NSString*)newName year:(int)newYear length:(int)newLength filesize:(NSString*)newFileSize rating:(int)newRating genre:(NSArray*)newGenre plot:(NSString*)newPlot;
- (void) encodeWithCoder : (NSCoder *)encode ;
- (id) initWithCoder : (NSCoder *)decode;

@end

Movie.m:

@implementation Movie

@synthesize name;
@synthesize year;
@synthesize length;
@synthesize file_size;
@synthesize rating;
@synthesize genre;
@synthesize plot;

-(id)initWithName:(NSString *)newName year:(int)newYear length:(int)newLength filesize:(NSString *)newFileSize rating:(int)newRating genre:(NSArray *)newGenre plot:(NSString *)newPlot{
    self.name = newName;
    self.year = newYear;
    self.length = newLength;
    self.file_size = newFileSize;
    self.rating = newRating;
    self.genre = newGenre;
    self.plot = newPlot;
    return self;
}
- (void)encodeWithCoder:(NSCoder *)encode;
{
    [encode encodeObject:name forKey:@"name"];
    [encode encodeInt32:year forKey:@"year"];
    [encode encodeInt32:length forKey:@"length"];
    [encode encodeObject:file_size forKey:@"file_size"];
    [encode encodeInt32:rating forKey:@"rating"];
    [encode encodeObject:genre forKey:@"genre"];
    [encode encodeObject:plot forKey:@"plot"];
}

- (id)initWithCoder:(NSCoder *)decode;
{
        NSString *name_decode = [decode decodeObjectForKey:@"name"];
        int year_decode = [decode decodeInt32ForKey:@"year"];
        int length_decode = [decode decodeInt32ForKey:@"length"];
    NSString *file_size_decode = [decode decodeObjectForKey:@"file_size"];
    int rating_decode = [decode decodeInt32ForKey:@"rating"];
    NSArray *genre_decode = [decode decodeObjectForKey:@"genre"];
    NSString *plot_decode =[decode decodeObjectForKey:@"plot"];
    return [self initWithName:name_decode year:year_decode length:length_decode filesize:file_size_decode rating:rating_decode genre:genre_decode plot:plot_decode];
}

@end

保存操作(电影是包含我的对象的 NSMutableArray):

NSUserDefaults *userDefault=[NSUserDefaults standardUserDefaults];
    NSData *encodedData = [NSKeyedArchiver archivedDataWithRootObject:Movies];
    [userDefault setObject:encodedData forKey:[NSString stringWithFormat:@"MOVIES"]];

加载操作:

NSData *decodedData = [userDefault objectForKey: [NSString stringWithFormat:@"MOVIES"]];
    NSArray *decodedArray =[NSKeyedUnarchiver unarchiveObjectWithData: decodedData];

返回的数组总是 (null)...我不知道 我尝试了在互联网上找到的几种不同类型的代码片段 and/or Whosebug

一个快速测试是查看可变数组本身是否实际上不是 nil。在 userDefaults.

中设置之前尝试输出可变数组

确保可变数组在尝试向其添加对象之前已初始化。

movies = [[NSMutableArray alloc] init];

您的Movie initWithName...方法不正确。必须是:

- (instancetype)initWithName:(NSString *)newName year:(int)newYear length:(int)newLength filesize:(NSString *)newFileSize rating:(int)newRating genre:(NSArray *)newGenre plot:(NSString *)newPlot {
    self = [super init];
    if (self) {
        self.name = newName;
        self.year = newYear;
        self.length = newLength;
        self.file_size = newFileSize;
        self.rating = newRating;
        self.genre = newGenre;
        self.plot = newPlot;
    }

    return self;
}

此外,您似乎在学习非常过时的教程。

  1. 您不需要为您的属性声明 ivars。
  2. 您不需要调用 @synthesize
  3. 您应该使用 ARC 而不是 MRC,因此您的 retain 属性应该是 strong(认为 NSString 属性应该是 copy.
  4. 您的 init 方法应该 return instancetype,而不是 id

考虑到所有这些,您的 Movie class 应该如下所示:

Movie.h

@interface Movie : NSObject <NSCoding>

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int year;
@property (nonatomic, assign) int length;
@property (nonatomic, copy) NSString *file_size;
@property (nonatomic, assign) int rating;
@property (nonatomic, strong) NSArray *genre;
@property (nonatomic, copy) NSString *plot;

- (instancetype)initWithName:(NSString *)newName year:(int)newYear length:(int)newLength filesize:(NSString *)newFileSize rating:(int)newRating genre:(NSArray *)newGenre plot:(NSString *)newPlot;

@end

Movie.m

@implementation Movie

- (instancetype)initWithName:(NSString *)newName year:(int)newYear length:(int)newLength filesize:(NSString *)newFileSize rating:(int)newRating genre:(NSArray *)newGenre plot:(NSString *)newPlot {
    self = [super init];
    if (self) {
        _name = newName;
        _year = newYear;
        _length = newLength;
        _file_size = newFileSize;
        _rating = newRating;
        _genre = newGenre;
        _plot = newPlot;
    }

    return self;
}

- (void)encodeWithCoder:(NSCoder *)encode;
{
    [encode encodeObject:self.name forKey:@"name"];
    [encode encodeInt32:self.year forKey:@"year"];
    [encode encodeInt32:self.length forKey:@"length"];
    [encode encodeObject:self.file_size forKey:@"file_size"];
    [encode encodeInt32:self.rating forKey:@"rating"];
    [encode encodeObject:self.genre forKey:@"genre"];
    [encode encodeObject:self.plot forKey:@"plot"];
}

- (instancetype)initWithCoder:(NSCoder *)decode;
{
    NSString *name_decode = [decode decodeObjectForKey:@"name"];
    int year_decode = [decode decodeInt32ForKey:@"year"];
    int length_decode = [decode decodeInt32ForKey:@"length"];
    NSString *file_size_decode = [decode decodeObjectForKey:@"file_size"];
    int rating_decode = [decode decodeInt32ForKey:@"rating"];
    NSArray *genre_decode = [decode decodeObjectForKey:@"genre"];
    NSString *plot_decode =[decode decodeObjectForKey:@"plot"];
    return [self initWithName:name_decode year:year_decode length:length_decode filesize:file_size_decode rating:rating_decode genre:genre_decode plot:plot_decode];
}

@end

您没有说明如何创建和填充 Movies 变量(应命名为 movies,而不是 Movies。确保它不是 nil.

此外,不要不必要地使用 stringWithFormat

您的保存代码应该是:

NSUserDefaults *userDefault=[NSUserDefaults standardUserDefaults];
NSData *encodedData = [NSKeyedArchiver archivedDataWithRootObject:movies];
[userDefault setObject:encodedData forKey:@"MOVIES"];

你的加载代码应该是:

NSData *decodedData = [userDefault objectForKey:@"MOVIES"];
NSArray *decodedArray = [NSKeyedUnarchiver unarchiveObjectWithData: decodedData];