iOS信息保存网络请求

iOS常见的数据存储方式

2016-07-12  本文已影响843人  智障小鲁班
plist存储

plist的文件名不能叫做“info”、“Info”之类的,这是因为与系统属性文件重名,而plist作为属性列表是一种XML格式的文件,拓展名为plist。如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,就可以使用writeToFile:atomically:方法直接将对象写到属性列表文件中,而Plist不能存储自定义对象,成功后会写入到Documents文件中(app);在ixcode中plist文件创建步骤为:NewFile —— IOS —— Resource —— Property List。
  plist存储代码实例:

  1. 加载plist
//获取Plist文件的全路径
NSString *path = [[NSBundle mainBundle] pathForResource:@"shops" ofType:@"plist"];
//加载plist文件
_shops = [NSArray arrayWithContentsOfFile:path];
  1. 属性列表——归档NSDictionary. 将数据封装成字典,将字典持久化到Documents/stu.plist文件中
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"15013141314" forKey:@"phone"];
[dict writeToFile:path atomically:YES];
  1. 属性列表——恢复NSDictionary; 读取Documents/stu.plist的内容,实例化NSDictionary.
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSLog(@"phone:%@", [dict objectForKey:@"phone"]);
UserDefaults(偏好设置存储)

很多iOS应用都支持偏好设置,比如保存用户名、密码、字体大小是否自动登录,等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能.偏好设置好处主要在于:不需要关心文件名,可以快速进行键值对存储,能够直接存储基本数据类型,从而成功后会写入到library(preference)中。
  UserDefaults(偏好设置存储)代码实例:

  1. 写入需保存的设置
[[NSUserDefaults standardUserDefaults] setFloat:18.0f forKey:@"text_size"]; 
  1. 读取上次保存的设置
float textSize = [[NSUserDefaults standardUserDefaults] floatForKey:@"text_size"];
  1. 注意:IOS7之前UserDefaults设置数据时,不是立即写入可能还没有写入磁盘应用程序就终止了导致数据丢失,可以通过调用synchornize方法强制写入;
IOS7之后已经实现即时写入,可以省略此步
[defaults synchronize];  //'siŋkrənaiz
NSKeyedArchiver

父类是NSCoder,归档成功会保存在Documents下,以".archive"后缀保存。如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,可以直接用NSKeyedArchiver进行归档和恢复,不是所有的对象都可以直接用这种方法进行归档,只有遵守了NSCoding协议的对象才可以。而NSCoding协议有2个方法: encodeWithCoder:每次归档对象时,都会调用这个方法。一般在这个方法里面指定如何归档对象中的每个实例变量,可以使用encodeObject:forKey:  方法归档实例变量 initWithCoder:每次从文件中恢复(解码)对象时,都会调用这个方法。一般在这个方法里面指定如何解码文件中的数据为对象的实例变量,可以使用decodeObject:forKey方法解码实例变量。

  1. 系统对象通过NSKeyedArchiver保存与读取数据
    1) 归档一个NSArray对象到Documents/array.archive
NSArray *array = [NSArray arrayWithObjects:@”a”,@”b”,nil];
[NSKeyedArchiver archiveRootObject:array toFile:path];

2)恢复(解码)NSArray对象

NSArray *array = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

3)需要遵守

 - (void)encodeWithCoder:(NSCoder *)encoder {
    [encoder encodeObject:self.name forKey:@"name"];
    [encoder encodeInt:self.age forKey:@"age"];
    [encoder encodeFloat:self.height forKey:@"height"];
}
- (id)initWithCoder:(NSCoder *)decoder {
   self.name = [decoder decodeObjectForKey:@"name"];
   self.age = [decoder decodeIntForKey:@"age"];
   self.height = [decoder decodeFloatForKey:@"height"];
   return self;
}
  1. 自定义对象通过NSKeyedArchiver保存与读取数据
 1)归档(编码)
Person *person = [[[Person alloc] init] autorelease];
person.name = @"MJ";
person.age = 27;
person.height = 1.83f;
[NSKeyedArchiver archiveRootObject:person toFile:path];
2)恢复(解码)
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
3)注意
   如果父类也遵守了NSCoding协议,应该在encodeWithCoder:方法中加上一句:
[super encodeWithCode:encode];

确保继承的实例变量也能被编码,即也能被归档,应该在initWithCoder:方法中加上一句:

self = [super initWithCoder:decoder];

确保继承的实例变量也能被解码,即也能被恢复.

利用归档实现深复制
//比如对一个Person对象进行深复制,临时存储person1的数据

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person1];

//解析data,生成一个新的Person对象
Student *person2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];

//分别打印内存地址
NSLog(@"person1:0x%x", person1); // person1:0x7177a60
NSLog(@"person2:0x%x", person2); // person2:0x7177cf0
归档

NSKeyedArchiver专门用来做自定义对象归档

// 什么时候调用:当一个对象要归档的时候就会调用这个方法归档
// 作用:告诉苹果当前对象中哪些属性需要归档
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInt:_age forKey:@"age"];
}

// 什么时候调用:当一个对象要解档的时候就会调用这个方法解档
// 作用:告诉苹果当前对象中哪些属性需要解档
// initWithCoder什么时候调用:只要解析一个文件的时候就会调用
- (id)initWithCoder:(NSCoder *)aDecoder
{
    #warning  [super initWithCoder]
    if (self = [super init]) {
        // 解档
        // 注意一定要记得给成员属性赋值
      _name = [aDecoder decodeObjectForKey:@"name"];
      _age = [aDecoder decodeIntForKey:@"age"];
    }
    return self;
}
SQLite及FMDB

采用SQLite数据库来存储数据。SQLite作为一中小型数据库,应用ios中,跟前几种保存方式相比,相对比较复杂一些,常用框架 FMDB,FMDB使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码,提供了多线程安全的数据库操作方法,有效地防止数据混乱。

  1. 打开数据库
     通过指定SQLite数据库文件路径来创建FMDatabase对象。
 FMDatabase *db = [FMDatabase databaseWithPath:path];
 if (![db open]) {
     NSLog(@"数据库打开失败!");
 }

文件路径有三种情况:
1)具体文件路径:如果不存在会自动创建空字符串。
2)@"":会在临时目录创建一个空的数据库,当FMDatabase连接关闭时,数据库文件也被删除。
3)nil:会创建一个内存中临时数据库,当FMDatabase连接关闭时,数据库会被销毁。

  1. 执行更新

在FMDB中,除查询以外的所有操作,都称为“更新”,create、drop、insert、update、delete等,使用executeUpdate:方法执行更新

- (BOOL)executeUpdate:(NSString*)sql, ...
- (BOOL)executeUpdateWithFormat:(NSString*)format, ...
- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments

// 示例
[db executeUpdate:@"UPDATE t_student SET age = ? WHERE name = ?;", @20, @"Jack"]

3 .执行查询

 - (FMResultSet *)executeQuery:(NSString*)sql, ...
  - (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...
  - (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments

  // 查询数据
  FMResultSet *rs = [db executeQuery:@"SELECT * FROM t_student"];

  // 遍历结果集
  while ([rs next]) {
      NSString *name = [rs stringForColumn:@"name"];
      int age = [rs intForColumn:@"age"];
      double score = [rs doubleForColumn:@"score"];
  }

4 . 关于FMDatabaseQueue
  FMDatabase这个类是线程不安全的,如果在多个线程中同时使用一个FMDatabase实例,会造成数据混乱等问题,为了保证线程安全,FMDB提供方便快捷的FMDatabaseQueue类.
4.1 FMDatabaseQueue的创建


  FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];
简单使用
  [queue inDatabase:^(FMDatabase *db) {
      [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
      [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
      [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];

      FMResultSet *rs = [db executeQuery:@"select * from t_student"];
      while ([rs next]) {
          // …
      }
  }];

4.2 使用事务

  [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
      [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jack"];
      [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Rose"];
      [db executeUpdate:@"INSERT INTO t_student(name) VALUES (?)", @"Jim"];

      FMResultSet *rs = [db executeQuery:@"select * from t_student"];
      while ([rs next]) {
          // …
      }
  }];

4.3 事务回滚

  rollback = YES;
上一篇下一篇

猜你喜欢

热点阅读