天天看點

iOS 使用FMDB與FMDBMigrationManager結合 進行資料庫版本的更新

在iOS 中進行資料儲存一般使用的都是FMDB,一般應用中字段定義好就不會再進行修改或者添加,如果嚴謹的話,我們需要為資料庫添加增加字段的功能,目前項目中使用的是FMDB與FMDBMigrationManager結合使用,儲存資料庫版本号并對資料庫進行資料庫更新操作

根據網上的解釋有兩種方法,這裡隻介紹其中的一種方法:

另一個方法請看這裡https://www.jianshu.com/p/6cfc38a6d2c0

建立一個類:Migration遵循FMDBMigration協定,name:更新描述(可以置為nil),version:目前資料庫的版本号,array:進行的資料庫操作;

#import <Foundation/Foundation.h>
#import "FMDBMigrationManager.h"

@interface Migration : NSObject<FMDBMigrating>

@property (nonatomic, readonly) NSString *name;
@property (nonatomic, readonly)uint64_t version;

/**
 @param name 資料庫更新描述
 @param version 目前版本号
 @param updateArray 資料庫操作,由于可能有多個,是以使用數組
 @return  Migration
 */
- (instancetype)initWithName:(NSString *)name andVersion:(uint64_t)version andExecuteUpdateArray:(NSArray *)updateArray;

- (BOOL)migrateDatabase:(FMDatabase *)database error:(out NSError *__autoreleasing *)error;

@end
           
#import "Migration.h"

@interface Migration()

@property (nonatomic, copy) NSString *myName;
@property (nonatomic, assign) uint64_t myVersion;
@property (nonatomic, strong) NSArray *updateArray;

@end

@implementation Migration

- (instancetype)initWithName:(NSString *)name andVersion:(uint64_t)version andExecuteUpdateArray:(NSArray *)updateArray
{
    if (self = [super init]) {
        _myName = name;
        _myVersion = version;
        _updateArray = updateArray;
    }
    return self;
}

- (NSString *)name {
    return _myName;
}

- (uint64_t)version {
    return _myVersion;
}

- (BOOL)migrateDatabase:(FMDatabase *)database error:(out NSError *__autoreleasing *)error {
    for (NSString *updateStr in _updateArray) {
        [database executeUpdate:updateStr];
    }
    return YES;
}

@end
           
// #define CACHESDIRECTORY ([NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0])

    NSString *documentsPath = CACHESDIRECTORY; // [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    
    // 檔案路徑
    
    NSString *filePath = [documentsPath stringByAppendingPathComponent:@"express.sqlite"];
    NSLog(@"filePath == %@",filePath);
    // 執行個體化FMDataBase對象
    
    _db = [FMDatabase databaseWithPath:filePath];
    
    [_db open];

    FMDBMigrationManager *manager = [FMDBMigrationManager  managerWithDatabaseAtPath:filePath migrationsBundle:[NSBundle mainBundle]];
    // 這裡 migration_1 代表為建立
    Migration *migration_1 = [[Migration alloc] initWithName:@"建立table表" andVersion:1 andExecuteUpdateArray:@[@"CREATE TABLE 'express' ('express_number' VARCHAR(255),'express_name' VARCHAR(255),'express_type' VARCHAR(255), 'express_date' VARCHAR(255),'express_message' VARCHAR(255), 'express_image' ARCHAR(255))"]];
    [manager addMigration:migration_1];
    // 增加字段
    Migration * migration_2=[[Migration alloc]initWithName:@"USer表新增字段email" andVersion:2 andExecuteUpdateArray:@[@"alter table express add email text"]];
    [manager addMigration:migration_2];
    
    BOOL resultState = NO;
    NSError *error = nil;
    if (!manager.hasMigrationsTable) {
        resultState = [manager createMigrationsTable:&error];
    }
    resultState = [manager migrateDatabaseToVersion:UINT64_MAX progress:nil error:&error];
    NSLog(@"Has `schema_migrations` table?: %@", manager.hasMigrationsTable ? @"YES" : @"NO");
    NSLog(@"Origin Version: %llu", manager.originVersion);
    NSLog(@"Current version: %llu", manager.currentVersion);
    NSLog(@"All migrations: %@", manager.migrations);
    NSLog(@"Applied versions: %@", manager.appliedVersions);
    NSLog(@"Pending versions: %@", manager.pendingVersions);
    
    [_db close];