zoukankan      html  css  js  c++  java
  • iOS开发~App初始化或者升级涉及本地数据库迁移的问题

    总体思路

    一般app启动之后,都有一个初始化的过程。此外后续app升级,还需要考虑数据迁移。所以初始化和数据迁移的框架,在初期的版本就要考虑好

    总结一下我们的app采取的方案:

    1、在持久化的文件夹内(比如UserDefaults或者Documents目录),用一个字段保存老版本号

    2、在开始初始化之前,读取老版本号,以及当前版本号

    3、如果该应用是第一次加载,那么老版本号就取不到(因为是初次加载,这个字段还没有保存),那么就可以执行初始化过程;如果取到了老版本号,就不执行初始化

    4、初始化完成之后,执行数据迁移。因为有老版本号和新版本号,所以可以通过对比,实现增量式的迁移

    5、上述动作都完成之后,刷新老版本号

    6、下次正常启动,就不会再初始化,也不会执行数据迁移了;如果是安装新版本,由于当前版本号刷新,又会触发数据迁移

    用户切换账户的场景

    上面说的是比较简单的场景。如果应用允许多用户切换账号,而且不同用户的数据是分离的,就更复杂一些

    首先标识老版本号的字段不能保存在UserDefaults里,因为UserDefaults是用户共享的。这样当A用户初始化之后,老版本号就存在了。切换到B用户,发现老版本号已存在,则不会执行初始化,其实这时候B用户的数据文件还没有创建好。所以需要把老版本号存在单独的地方,比如每个用户各自的sqlite文件中

    然后,读取老版本号的时候,也要根据用户的独立标识去查询

    改进

    目前暂时是把老版本号保存在sqlite里,但是这样首次读取的时候,判断逻辑比较麻烦。需要判断sqlite文件是否存在,然后要判断table有没有,最后才能取值。如果用文本保存可能会稍微方便一点,比存在sqlite里,少了一个判断table是否存在的步骤

    示意代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    -(BOOL) needInit
    {
        return [oldVersion isEqual: @"0"];
    }
     
    -(NSString*) oldVersion
    {
        return oldVersion;
    }
     
    -(NSString*) currentVersion
    {
        return currentVersion;
    }
     
    #pragma mark - private method
     
    -(void) initOldVersion
    {
        // 数据库文件不存在,oldVersion设为0
        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSString *dbFilePath = [YLSGlobalUtils getDatabaseFilePath];
        if(![fileManager fileExistsAtPath:dbFilePath]){
            oldVersion = @"0";
            return;
        }
         
        // 数据库文件打开失败,oldVersion设为0
        FMDatabase *db = [FMDatabase databaseWithPath:dbFilePath];
        if(![db open]){
            oldVersion = @"0";
            return;
        }
         
        // tb_clientstage表不存在,oldVersion设为0
        int tableCount = 0;
        FMResultSet *rs = [db executeQuery:@"select count(*) as count from sqlite_master where type='table' and name='tb_clientstage'"];
        if([rs next]){
            tableCount = [rs intForColumn:@"count"];
        }
        if(tableCount == 0){
            oldVersion = @"0";
            [db close];
            return;
        }
         
        // 设置oldVersion
        rs = [db executeQuery:@"select * from tb_clientstage where id = '1' and tableno = '0'"];
        if([rs next]){
            oldVersion = [rs stringForColumn:@"version"];
        }else{
            oldVersion = @"0";
        }
        [db close];
    }
     
    -(void) initCurrentVersion
    {
        NSDictionary* infoDict =[[NSBundle mainBundle] infoDictionary];
        NSString* versionNum =[infoDict objectForKey:@"CFBundleVersion"];
        currentVersion = versionNum;
    }


    然后,是否进行初始化的判断:

    1
    2
    3
    4
    5
    6
    7
    8
    clientInfo = [YLSClientInfo new];
     
    if([clientInfo needInit]){
        [self createEverythingForFirstTime];// 初始化时才执行
    }
    [self allTheTime];// 任何时候都执行
     
    [migrationHelper doMigration:clientInfo];


    增量迁移:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    -(void) doMigration:(YLSClientInfo*)clientInfo
    {
        NSString *oldVersion = [clientInfo oldVersion];
        NSString *currentVersion = [clientInfo currentVersion];
         
        // 正常登陆,不需要数据迁移
        if([oldVersion isEqualToString:currentVersion]){
            return;
        }
         
        // 全新安装,非升级,不需要数据迁移
        if([oldVersion isEqualToString:@"0"]){
            return;
        }
         
        // 以下均是版本升级,需要数据迁移
        if([oldVersion isEqualToString:@"1.0.0"]){
            [script1 doMigration];
            [script2 doMigration];
            [script3 doMigration];
            [script4 doMigration];
            return;
        }
         
        // 其他的情况
    }

     

  • 相关阅读:
    解决Linux 环境 GLIBCXX_3.4.15' not found问题
    同步和异步接口,你还有疑惑么?
    SQL中内连接和外连接的区别
    Linux常用操作指令(面试专用)
    关于支付类的一些测试关注点及异常点
    jenkins持续集成 python selenium(windows本地)
    从ghost映像.gho文件快速创建vmware虚拟机
    阿里p3c(代码规范,eclipse插件、模版,idea插件)
    logback错误日志发送邮件
    C#中的异步陷阱
  • 原文地址:https://www.cnblogs.com/kevingod/p/3912514.html
Copyright © 2011-2022 走看看