An extension of FMDB to provide ORM and migration functionality for your iOS application.
- iOS 7.0 or later
- Xcode5 or later
- ARC
Note: I am testing this product on the above condition.
You can install FMDBx via CocoaPods. Add the following line to your Podfile.
pod 'FMDBx'
Database Manager:FMXDatabaseManager
class is a singleton instance that manages sqlite database files and FMDatabase instances connecting them. You can get it the following code.
FMXDatabaseManager *manager = [FMXDatabaseManager sharedManager];
At first, you need to register a database that is used in your app to Database Manager.
[[FMXDatabaseManager sharedManager] registerDefaultDatabaseWithPath:@"database.sqlite" migration:nil];
At the above example, you don't need to place database.sqlite
file by hand.
FMXDatabaseManager
class automatically create initial empty database.sqlite
file in the NSDocumentDirectory
if it doesn't exist.
FMDatabase *db = [[FMXDatabaseManager sharedManager] defaultDatabase];
[db open];
// your code for databse operations
[db close];
FMXDatabaseManager
can have a migration object to initialize and migrate database schema.
Create your migration class.
@interface MyMigration : FMXDatabaseMigration
@end
@implementation MyMigration
- (void)migrate
{
[self upToVersion:1 action:^(FMDatabase *db){
[db executeUpdate:@""
"create table users ("
" id integer primary key autoincrement,"
" name text not null,"
" age integer not null,"
" is_male BOOL not null,"
" created_at integer not null,"
" updated_at integer not null"
")"
];
}];
[self upToVersion:2 action:^(FMDatabase *db){
// ... schema changes for version 2
}];
[self upToVersion:3 action:^(FMDatabase *db){
// ... schema changes for version 3
}];
// ...etc
}
@end
Register a database with an instance of migration class. It runs migration tasks.
[[FMXDatabaseManager sharedManager] registerDefaultDatabaseWithPath:@"database.sqlite"
migration:[[MyMigration alloc] init]];
It is designed like ActiveRecord.
You need to define model classes for each tables.
By default, a model class automatically maps a table which is named pluralized class name without prefix.(It's not strict. Just add s
end of the term).
For example, ABCUser
model class maps users
table at default.
@interface ABCUser : FMXModel
@property (strong, nonatomic) NSNumber *id;
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSNumber *age;
@property (assign, nonatomic) BOOL isMale;
@property (strong, nonatomic) NSDate *createdAt;
@property (strong, nonatomic) NSDate *updatedAt;
@end
You need to define defaultTableMap
method like the following to map each properties with table columns.
@implementation ABCUser
+ (void)defaultTableMap:(FMXTableMap *)table {
[table hasIntIncrementsColumn:@"id"]; // defines as a primary key.
[table hasStringColumn:@"name"];
[table hasIntColumn:@"age"];
[table hasBoolColumn:@"is_male"];
[table hasDateColumn:@"created_at"];
[table hasDateColumn:@"updated_at"];
}
@end
The model class needs primary key. So you need to define primary key configuration. Please see below example.
[table hasIntIncrementsColumn:@"id"];
// or
[table hasIntColumn:@"id" withPrimaryKey:YES];
If you want to change a mapped table name from a default, you can specify table name like the following.
@implementation ABCUser
- (void)defaultTableMap:(FMXTableMap *)table
{
[table setTableName:@"custom_users"];
}
@end
You can use a model class to insert, update and delete data.
ABCUser *user = [[ABCUser alloc] init];
user.name = @"Kohki Makimoto";
user.age = @(34);
// insert
[user save];
// update
user.age = @(44);
[user save];
// delete
[user delete];
ABCUser *user = (ABCUser *)[ABCUser modelByPrimaryKey:@(1)];
NSLog(@"Hello %@", user.name);
You can get a model.
ABCUser *user = (ABCUser *)[ABCUser modelWhere:@"name = :name" parameters:@{@"name": @"Kohki Makimoto"}];
You can get multiple models.
NSArray *users = [ABCUser modelsWhere:@"age = :age" parameters:@{@"age": @34}];
for (ABCUser *user in users) {
NSLog(@"Hello %@!", user.name);
}
# Count all users.
NSInteger count = [ABCUser count];
# Count users whose name is 'Kohki Makimoto'.
NSInteger count = [ABCUser countWhere:@"name = :name" parameters:@{@"name": @"Kohki Makimoto"}];
You can add some data in your migration task or other places.
@interface MyMigration : FMXDatabaseMigration
@end
@implementation MyMigration
- (void)migrate
{
[self upToVersion:1 action:^(FMDatabase *db){
[db executeUpdate:@""
"create table users ("
" id integer primary key autoincrement,"
" name text not null,"
" age integer not null,"
" is_male BOOL not null,"
" created_at integer not null,"
" updated_at integer not null"
")"
];
[FMXCsvTable foreachFileName:@"users.csv" process:^(NSDictionary *row) {
[ABCUser createWithValues:row database:db];
}];
}];
}
@end
CSV file is like the following. The header line is must.
id,name,age,is_male,created_at,updated_at
1,Kohki Makimoto1,34,1,2010-12-01T21:35:43+0900,2010-12-01T21:35:43+0900
2,Kohki Makimoto2,35,1,2010-12-01T21:35:43+0900,2010-12-01T21:35:43+0900
3,Kohki Makimoto3,36,0,2010-12-01T21:35:43+0900,2010-12-01T21:35:43+0900
4,Kohki Makimoto4,37,0,2010-12-01T21:35:43+0900,2010-12-01T21:35:43+0900
5,Kohki Makimoto5,38,1,2010-12-01T21:35:43+0900,2010-12-01T21:35:43+0900
6,Kohki Makimoto6,39,1,2010-12-01T21:35:43+0900,2010-12-01T21:35:43+0900
7,Kohki Makimoto7,40,0,2010-12-01T21:35:43+0900,2010-12-01T21:35:43+0900