FFDB 4.1.5

FFDB 4.1.5

测试已测试
Lang语言 Obj-CObjective C
许可证 MIT
发布最新发布2024年3月

Fidetro--verbose 维护。



FFDB 4.1.5

  • 作者:
  • fidetro

FFDB

DUB GitHub stars
更详细的使用介绍请参考 Wiki

前言

OC 版的 FFDB 之前已经打算放弃,但是由于 SwiftFFDB 的一轮重构,现在决定也重构 OC 版的,主要是对 sql 语句拼接这部分进行了优化,参考了 sqlite3 的 语法设计,整体来说变得更优雅了,同时,4.x 版本使用的是参数化查询,用来防止注入。

1.x 版本的文档请在此处 查看

2.x 版本的文档请在此处 查看

3.x 版本的文档请在此处 查看

正文

为什么会有 FFDB?

  1. 直接使用 FMDB 代码既不优雅又非常繁琐,而且并不能像使用 CoreData 那样面向对象来管理;
  2. 在项目中经常会遇到不得不使用数据库来存储数据的情况;
  3. 对于移动端数据库,我只使用过 FMDB,使用 CoreData 时觉得需要编写太多代码,后来放弃了,只使用 FMDB 没有使用 ORM 的便利,所以有 FFDB。

CoreData、Realm与对FMDB封装后的FFDB对比

以下部分代码摘自Realm文档

您可以在这里找到

CoreData插入对象
//Create a new Dog
Dog *newDog = [NSEntityDescription insertNewObjectForEntityForName:@"Dog" inManagedObjectContext:myContext];
newDog.name = @"McGruff";

//Save the new Dog object to disk
NSError *saveError = nil;
[newDog.managedObjectContext save:&saveError];

//Rename the Dog
newDog.name = @"Pluto";
[newDog.managedObjectContext save:&saveError];
Realm插入对象
//Create the dog object
Dog *newDog = [[Dog alloc] init];
newDog.name = @"McGruff";

//Save the new Dog object to disk (Using a block for the transaction)
RLMRealm *defaultRealm = [RLMRealm defaultRealm];
[defaultRealm transactionWithBlock:^{
[defaultRealm addObject:newDog];
}];

//Rename the dog (Using open/close methods for the transaction)
[defaultRealm beginWriteTransaction];
newDog.name = @"Pluto";
[defaultRealm commitWriteTransaction];

FFDB插入对象
Dog *newDog = [[Dog alloc] init];
newDog.name = @"McGruff";
[newDog insertObject];
//重命名狗,更新对象
newDog.name = @"Pluto";
[newDog updateObject];
CoreData查询
NSManagedObjectContext *context = self.managedObjectContext;

//A fetch request to get all dogs younger than 5 years old, in alphabetical order
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Dog" inManagedObjectContext:context];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 5"];

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];

NSFetchRequest *request = [[NSFetchRequest alloc] init];
request.entity = entity;
request.predicate = predicate;
request.sortDescriptors = @[sortDescriptor];

NSError *error;
NSArray *dogs = [moc executeFetchRequest:request error:&error];
Realm查询对象
RLMResults *dogs = [[Dog objectsWhere:@"age < 5"] sortedResultsUsingProperty:@"name" ascending:YES];
FFDB查询对象
NSArray<Dog *> *dogs = [Dog selectFromClassWhereFormat:@"where age < ? order by name" values:@[@"5"]];

类相当于一张表,对象即数据,这一设计思想贯穿整个结构

适用于何地和优势是什么?

  1. 当数据量很大,NSUserDefault和.plist无法满足需求时;
  2. 不熟悉基本数据库语句的同学;
  3. 无需进行复杂数据库操作;
  4. 通过runtime实现,无需接触sqlite语句(但仍需了解一些基础)就能实现增删改查;

如何使用?如何集成?

CocoaPods中这里

pod 'FFDB’,’~>4.x’ pod search FFDB如果没有找到,pod setup之后再试

如果不使用CocoaPod,请导入FMDB,并在target的Linked Frameworks and Libraries中导入libsqlite3.0.tbd

image

同时将目录中的这些文件拖入工程中

image

建立的类需要继承自FFDataBaseModel,声明属性即可,例如一个Person表中包含姓名、年龄字段。

@interface Person : FFDataBaseModel
/** 人名 **/
@property(nonatomic,copy) NSString *name;
/** 年龄 **/
@property(nonatomic,copy) NSString *age;
/** 设置主键字段 **/
@property(nonatomic,copy) NSString *priamryID;

//从4.x后版本,必须重写该方法,指定主键字段
+ (NSString *)primaryKeyColumn
{
    return @"primaryID";
}

插入:
Person *person = [[Person alloc]init];//创建对象
person.name = @"Fidetro";//设置属性
[person insertObject];//插入数据

查询:
[Person selectFromClassAllObject];//等同于查询Person表中所有的对象
[Person selectFromClassWhereFormat:@"where age = ? and name =  ? " values:@[@"15",@"Fidetro"]]//等同于查询年龄是15和名字叫Fidetro的数据
更新:

NSArray *personArray = [Person selectFromClassWhereFormat:@"where age = ? and name = ? " values:@[@"15",@"Fidetro"]]//先查询到要更新的数据
Person *person = [personArray lastObject];
person.age = @"24";
[person updateObject];

删除:
NSArray *personArray = [Person selectFromClassPredicateWithFormat:@"where name = 'fidetro' and age = '21'"];//先查询到要删除的数据
Person *person = [personArray lastObject];
[person deleteObject];

补充


1. 所有字段默认为TEXT类型,后续版本将增加自定义字段类型功能;
2. 所有继承自FFDataBaseModel的对象,在插入数据库后,都会自带一个primaryID作为唯一标识,同时这也是一个自增字段;
3. 目前FFDB仅提供了简单的增删改查接口,如果现有接口无法满足需求,可以通过以下几种方法进行扩展操作;通过获取这两个,可以自行结合FMDB原有方法进行操作。
4. 在4.x版本中,数据表模型必须重写+ (NSString *)primaryKeyColumn;方法指定主键字段。

获取FMDatabase对象
[FFDBManager database];
获取类在FMDB对应的表名
[Class tableName];
需要自定义表名,需要在子类重写 + (NSString *)tableName;
+ (NSString *)tableName
{
   return @"CustomTableName";
}


5. 如果某些属性不需要创建到表中,现在可以通过在子类中重写+ (NSArray *)memoryProperties来实现;

//例子
@interface TestModel : FFDataBaseModel
@property(nonatomic,copy) NSString *name;
/** 这是不需要加到表中的字段 **/
@property(nonatomic,copy) NSString *memory;
@property(nonatomic,copy) NSString *_id;
@property(nonatomic,assign) double time;
@end

+ (NSArray *)memoryPropertys
{
   return @[@"memory"];
}


6. 想要修改字段的存储类型,可以通过重写+ (NSDictionary *)columnTypes来自定义字段属性,未重写的字段默认为text类型;

+ (NSDictionary *)columnsType
{
    return @{@"time":@"double"};
}


7. 可以自定义字段名,通过重写+ (NSDictionary *)customColumns来实现;

这样表的字段是id建的,而不是_id
 + (NSDictionary *)customColumns
 {
 return @{@"_id":@"id"};
 }



8. 如果您的项目使用Swift,建议使用SwiftFFDB

Pod版本更新说明

UML类图

image