iOS开发系列--详细介绍数据存取

2020-01-18 17:36:10王旭


-(void)openDb:(NSString *)dbname{
  //取得数据库保存路径,通常保存沙盒Documents目录
  NSString *directory=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
  NSLog(@"%@",directory);
  NSString *filePath=[directory stringByAppendingPathComponent:dbname];
  //创建FMDatabase对象
  self.database=[FMDatabase databaseWithPath:filePath];
  //打开数据上
  if ([self.database open]) {
    NSLog(@"数据库打开成功!");
  }else{
    NSLog(@"数据库打开失败!");
  }
}

注意:dataWithPath中的路径参数一般会选择保存到沙箱中的Documents目录中;如果这个参数设置为nil则数据库会在内存中创建;如果设置为@””则会在沙箱中的临时目录创建,应用程序关闭则文件删除。

2.对于数据库的操作跟前面KCDbManager的封装是类似的,在FMDB中FMDatabase类提供了两个方法executeUpdate:和executeQuery:分别用于执行无返回结果的查询和有返回结果的查询。当然这两个方法有很多的重载这里就不详细解释了。唯一需要指出的是,如果调用有格式化参数的sql语句时,格式化符号使用“?”而不是“%@”、等。下面是两种情况的代码片段:

a.无返回结果


-(void)executeNonQuery:(NSString *)sql{
  //执行更新sql语句,用于插入、修改、删除
  if (![self.database executeUpdate:sql]) {
    NSLog(@"执行SQL语句过程中发生错误!");
  }
}

b.有返回结果


-(NSArray *)executeQuery:(NSString *)sql{
  NSMutableArray *array=[NSMutableArray array];
  //执行查询sql语句
  FMResultSet *result= [self.database executeQuery:sql];
  while (result.next) {
    NSMutableDictionary *dic=[NSMutableDictionary dictionary];
    for (int i=0; i<result.columnCount; ++i) {
      dic[[result columnNameForIndex:i]]=[result stringForColumnIndex:i];
    }
    [array addObject:dic];
  }
  return array;
}

对于有返回结果的查询而言,查询完返回一个游标FMResultSet,通过遍历游标进行查询。而且FMDB中提供了大量intForColumn、stringForColumn等方法进行取值。

并发和事务

我们知道直接使用libsqlite3进行数据库操作其实是线程不安全的,如果遇到多个线程同时操作一个表的时候可能会发生意想不到的结果。为了解决这个问题建议在多线程中使用FMDatabaseQueue对象,相比FMDatabase而言,它是线程安全的。

创建FMDatabaseQueue的方法是类似的,调用databaseQueueWithPath:方法即可。注意这里不需要调用打开操作。


-(void)openDb:(NSString *)dbname{
  //取得数据库保存路径,通常保存沙盒Documents目录
  NSString *directory=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
  NSLog(@"%@",directory);
  NSString *filePath=[directory stringByAppendingPathComponent:dbname];
  //创建FMDatabaseQueue对象
  self.database=[FMDatabaseQueue databaseQueueWithPath:filePath];
}