【问题标题】:What is the best way to save an NSMutableArray to NSUserDefaults?将 NSMutableArray 保存到 NSUserDefaults 的最佳方法是什么?
【发布时间】:2011-10-12 16:37:43
【问题描述】:

我有一个名为 Occasion 的自定义对象,定义如下:

#import <Foundation/Foundation.h>


@interface Occasion : NSObject {

NSString *_title;
NSDate *_date;
NSString *_imagePath;    

}

@property (nonatomic, retain) NSString *title;
@property (nonatomic, retain) NSDate *date;
@property (nonatomic, retain) NSString *imagePath;

现在我有一个 NSMutableArray 的场合,我想保存到 NSUserDefaults。我知道这是不可能的,所以我想知道哪种方法最简单?如果序列化是答案,那么如何?因为我阅读了文档,但无法完全理解它的工作方式。

【问题讨论】:

    标签: iphone serialization nsmutablearray nsuserdefaults custom-object


    【解决方案1】:

    您应该使用NSKeyedArchiver 之类的东西将数组序列化为NSData,将其保存到NSUserDefaults,然后稍后使用NSKeyedUnarchiver 对其进行反序列化:

    NSData *serialized = [NSKeyedArchiver archivedDataWithRootObject:myArray];
    [[NSUserDefaults standardUserDefaults] setObject:serialized forKey:@"myKey"];
    
    //...
    
    NSData *serialized = [[NSUserDefaults standardUserDefaults] objectForKey:@"myKey"];
    NSArray *myArray = [NSKeyedUnarchiver unarchiveObjectWithData:serialized];
    

    您需要在您的Occasion 类中实现NSCoding 协议并正确保存各种属性以使其正常工作。有关详细信息,请参阅Archives and Serializations Programming Guide。执行此操作不应该超过几行代码。比如:

    - (void)encodeWithCoder:(NSCoder *)coder {
        [super encodeWithCoder:coder];
    
        [coder encodeObject:_title forKey:@"_title"];
        [coder encodeObject:_date forKey:@"_date"];
        [coder encodeObject:_imagePath forKey:@"_imagePath"];
    }
    
    - (id)initWithCoder:(NSCoder *)coder {
        self = [super initWithCoder:coder];
    
        _title = [[coder decodeObjectForKey:@"_title"] retain];
        _date = [[coder decodeObjectForKey:@"_date"] retain];
        _imagePath = [[coder decodeObjectForKey:@"_imagePath"] retain];
    
        return self;
    }
    

    【讨论】:

    • 感谢您的帮助。我现在很清楚这个想法。最后一个问题:对于步骤 (NSArray *myArray = [NSKeyedUnarchiver unarchiveObjectWithData:serialized];) 会给我一个 NSArray 而我的原始数组是一个 NSMutableArray。那么我应该使用 [copy mutable] 之类的东西吗?
    • 如果它给你一个标准的NSArray 然后使用[array mutableCopy] 来获得一个可变版本。
    【解决方案2】:

    NSUserDefaults 用于用户偏好,不存储应用程序数据。使用CoreData 或将对象序列化到文档目录中。你需要让你的类实现NSCoding 协议才能工作。

    1) 在Occasion.h 中实现NSCoding

    @interface Occasion : NSObject <NSCoding>
    

    2) 实现Occasion.m中的协议

    - (id)initWithCoder:(NSCoder *)aDecoder {
    
        if (self = [super init]) {
    
            self.title = [aDecoder decodeObjectForKey:@"title"];
            self.date = [aDecoder decodeObjectForKey:@"date"];
            self.imagePath = [aDecoder decodeObjectForKey:@"imagePath"];
    
        }            
        return self;
    }
    
    - (void)encodeWithCoder:(NSCoder *)aCoder {
    
        [aCoder encodeObject:title forKey:@"title"];
        [aCoder encodeObject:date forKey:@"date"];
        [aCoder encodeObject:imagePath forKey:@"imagePath"];
    }
    

    3) 将数据归档到文档目录中的文件中

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                        NSUserDomainMask, YES);
    NSString *documentsPath = [paths objectAtIndex:0];
    NSString *path= [documentsPath stringByAppendingPathComponent:@“occasions”];
    [NSKeyedArchiver archiveRootObject:occasions toFile:path];
    

    4) 取消归档...

    NSMutableArray *occasions = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
    

    【讨论】:

    • 感谢您的回答。我的另一个问题是:我在 Occasion 对象中已经有 2 个方法称为:( - (id)init AND - (id)initWithTitle:(NSString *)title date:(NSDate *)date imagePath:(NSString *)imagePath ) 现在每当我想创建新的 Occasion 实例时,我应该取消这 2 种方法并改用 initWithCoder 和 encodeWithCoder 吗?
    • 不,当您要创建对象时,仍然使用 init 或 initWithTitle:date:imagePath。编码器方法仅用于序列化。
    【解决方案3】:

    您可以在Occasion 中实现NSCoding

    然后您使用[NSKeyedArchiver archivedDataWithRootObject:myArray] 从数组中创建一个NSData 对象。您可以将其放入用户默认值中。

    【讨论】:

      猜你喜欢
      • 2013-04-16
      • 2010-09-08
      • 2015-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-02
      相关资源
      最近更新 更多