IOS数据持久化总结

概论

所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据。在iOS开发中,常用的5种方案:

  • plist文件(属性列表)
  • preference(偏好设置)
  • NSKeyedArchiver(归档)
  • SQLite 3
  • CoreData
结构

沙盒就是一个文件夹,目录结构如下:

"应用程序包"
Documents
Library
    Caches
    Preferences
tmp
目录类型
  • "应用程序包": 这里面存放的是应用程序的源文件,包括资源文件和可执行文件。

      NSString *path = [[NSBundle mainBundle] bundlePath];
      NSLog(@"%@", path);
    
  • Documents: 最常用的目录,iTunes同步该应用时会同步此文件夹中的内容,适合存储重要数据。

      //第一种方法:
      NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
      //第二个参数 代表从用户文件夹下找, 第三个参数 代表是否显示路径全称,如果为no,那么输出为~/Documents/...
      NSLog(@"%@", path);
      
      //第二种方法: 
      //获取当前应用沙盒的根目录 
      NSString *homePath = NSHomeDirectory(); 
      //拼接路径 
      NSString *docPath = [homePath stringByAppendingPathComponent:@"Documents"];
    
  • Library/Caches: iTunes不会同步此文件夹,适合存储体积大,不需要备份的非重要数据。

      NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;
      NSLog(@"%@", path);
    
  • Library/Preferences: iTunes同步该应用时会同步此文件夹中的内容,通常保存应用的设置信息。

      //NSUserDefaults存储的位置:
      ///Library/Preferences/.plist
    
  • tmp: iTunes不会同步此文件夹,系统可能在应用没运行时就删除该目录下的文件,所以此目录适合保存应用中的一些临时文件,用完就删除。

      NSString *path = NSTemporaryDirectory();
      NSLog(@"%@", path);
    
存储数据类型和存储方法
  • plist文件存取方式(位置任意)

属性列表是一种XML格式的文件,拓展名为plist,可以被序列化的类型只有如下几种:

存储时使用writeToFile: atomically:方法。 其中atomically表示是否需要先写入一个辅助文件,再把辅助文件拷贝到目标文件地址。这是更安全的写入文件方法,一般都写YES

  1. NSArray;

  2. NSMutableArray;

  3. NSDictionary;

  4. NSMutableDictionary;

  5. NSData;

  6. NSMutableData;

  7. NSString;

  8. NSMutableString;

  9. NSNumber;

  10. NSDate;

    //1.获得文件路径
    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
    NSString *fileName = [path stringByAppendingPathComponent:@"123.plist"];
    
    //2.存储
    NSArray *array = @[@"123", @"456", @"789"];
    [array writeToFile:fileName atomically:YES];
    
    //3.读取
    NSArray *result = [NSArray arrayWithContentsOfFile:fileName];
    NSLog(@"%@", result);
    

有一点需要注意,就是存取字符串的时候,最好不要使用plist文件,因为plist本身不支持字符串(plist文件其根节点处,只有数组和字典两个选项),而且字符串的存取方法也已经过期。

  • 使用NSUserDefaults存储到Preference中(位置固定)

      //1.获得NSUserDefaults文件
      NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
      //2.向文件中写入内容
      [userDefaults setObject:@"AAA" forKey:@"a"];
      [userDefaults setBool:YES forKey:@"sex"];
      [userDefaults setInteger:21 forKey:@"age"];
      //2.1立即同步
      [userDefaults synchronize];
      //3.读取文件
      NSString *name = [userDefaults objectForKey:@"a"];
      BOOL sex = [userDefaults boolForKey:@"sex"];
      NSInteger age = [userDefaults integerForKey:@"age"];
      NSLog(@"%@, %d, %ld", name, sex, age);
    

注意:偏好设置是专门用来保存应用程序的配置信息的,一般不要在偏好设置中保存其他数据。如果没有调用synchronize方法,系统会根据I/O情况不定时刻地保存到文件中。所以如果需要立即写入文件的就必须调用synchronize方法。 偏好设置会将所有数据保存到同一个文件中。即preference目录下的一个以此应用包名来命名的plist文件。

* 使用NSKeyedArchiver归档存储(位置任意)

归档在iOS中是另一种形式的序列化,需要遵循NSCoding协议。

  1. 遵循NSCoding协议

     //1.遵循NSCoding协议
     @interface Person : NSObject  //2.设置属性
     @property (strong, nonatomic) UIImage *avatar;
     @property (copy, nonatomic) NSString *name;
     @property (assign, nonatomic) NSInteger age;
     @end
    
     //解档
     - (id)initWithCoder:(NSCoder *)aDecoder {
         if ([super init]) {
             self.avatar = [aDecoder decodeObjectForKey:@"avatar"];
             self.name = [aDecoder decodeObjectForKey:@"name"];
             self.age = [aDecoder decodeIntegerForKey:@"age"];
         }
         return self;
     }
     //归档
     - (void)encodeWithCoder:(NSCoder *)aCoder {
         [aCoder encodeObject:self.avatar forKey:@"avatar"];
         [aCoder encodeObject:self.name forKey:@"name"];
         [aCoder encodeInteger:self.age forKey:@"age"];
     }
    

特别注意:

如果需要归档的类是某个自定义类的子类时,就需要在归档和解档之前先实现父类的归档和解档方法。即 [super encodeWithCoder:aCoder] 和 [super initWithCoder:aDecoder] 方法;

  1. 用法

     //存
     NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,      NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
     Person *person = [[Person alloc] init];
     person.avatar = self.avatarView.image;
     person.name = self.nameField.text;
     person.age = [self.ageField.text integerValue];
     [NSKeyedArchiver archiveRootObject:person toFile:file];
     
     //取
     NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];
     Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file];
     if (person) {
         self.avatarView.image = person.avatar;
         self.nameField.text = person.name;
         self.ageField.text = [NSString stringWithFormat:@"%ld", person.age];
     }
    

注意:

  • 必须遵循并实现NSCoding协议
  • 保存文件的扩展名可以任意指定
  • 继承时必须先调用父类的归档解档方法

你可能感兴趣的:(IOS数据持久化总结)