ios - 当应用程序变为事件状态时,文件已加密或不是数据库消息

标签 ios iphone objective-c sqlite

我偶尔会遇到无法从 iPad 应用程序访问 sqlite 数据库的情况。我已使用 FMDatabase 访问 sqlite 数据库,但未在我的配置文件中启用 DataProtection。而且 sqlite 版本为 3。启用密码的设备会发生这种情况。当设备进入休眠状态而我的应用程序位于前台时,当用户输入密码时,此错误会随机出现。一旦用户成功输入密码,我的应用程序就会进入前台,并且突然无法使用 sqlite 代码 26 访问数据库:文件已加密或不是数据库

有人可以帮我解决这个问题吗?

我添加了一个发生的地方

-(NSString*)getValueForSetting:(NSString*)settingName{
    __block NSString *settingValue ;
    NSString *sql = [NSString stringWithFormat:@"SELECT SettingValue FROM Settings where SettingName = '%@' ",settingName];
    FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:[DatabaseUtility getDBPath]];
    @try{
        [queue inDatabase:^(FMDatabase *database) {
            FMResultSet *results = [database executeQuery:sql];
            if (![database hadError]) {
                if([results next]){
                    settingValue = [results stringForColumn:@"SettingValue"];
                }
            }
            else
            {
                NSLog(@"Database error,get setting value %d: %@", [database lastErrorCode], [database lastErrorMessage]);
            }
            [results close];
        }];
    }
    @catch(NSException *exception){
        NSLog(@"0002,ERR,MemberDataAccess,getiPadDisplayName:(NSString*)memberID, %@",[exception description]);
    }
    @finally {
        [queue close];
    }

    return settingValue;
}

这里我得到了以下输出

Database error,get setting value 26: file is encrypted or is not a database

编辑1:

我能够隔离出现问题的代码片段。在 applicationDidBecomeActive: 方法中 我正在调用以下方法。该方法用于将 NSLog 重定向到文件。

-(void) redirectConsoleLogToDocumentFolder
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                         NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];

    NSString *customPath=[documentsDirectory stringByAppendingPathComponent:@"LogFiles"];

    NSFileManager *manager=[NSFileManager defaultManager];
    if (![manager fileExistsAtPath:customPath])  
        [manager createDirectoryAtPath: customPath withIntermediateDirectories:YES attributes:nil error:nil];

    NSLog(@" DeviceLogs Class : custom path: %@",customPath);

    NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
    [dateFormat setDateFormat:@"yyyy-MM-dd"];
    [GlobalSettingsSingelton setLocale:&dateFormat];
    NSDate *today = [NSDate date];

    NSString *todaysDate = [[NSString alloc]initWithFormat:@"%@",[dateFormat stringFromDate:today]];
    NSString *logFile = [[NSString alloc]initWithFormat:@"Log_%@.txt",todaysDate];
    NSString *logPath = [customPath
                         stringByAppendingPathComponent:logFile];

    freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}

有时,在调用此方法后,我的数据库文件会损坏或加密,并在尝试访问数据库时出现上述错误。如果我评论这一行应用程序可以正常工作。

为了隔离问题,我在 freopen() 之前和之后调用了两个数据库访问方法。我在该方法之后添加的数据库访问方法给出了文件已加密或不是数据库错误,而以前的数据库访问方法运行时没有该问题。

我无法想象这个问题,因为 NSLog 重定向与数据库文件无关。它是如何加密或损坏的。请有人解释一下这一点。

最佳答案

您好,我终于找到了原因。第一this这篇文章帮助我了解了有关 sqlite 应用程序损坏的线索。它表明我怀疑与我的问题有关的一个原因。

We have seen cases where a file descriptor was open on a log file, then that file descriptor was
 closed and reopened on an SQLite database. Later, some other thread continued to write log 
information into the old file descriptor, not realizing that the log file had been closed already.
 But because the file descriptor had been reopened by SQLite, the information that was intended to 
go into the log file ended up overwriting parts of the SQLite database, leading to corruption of the 
database.

通过编写示例应用程序,我能够重现此问题。为此,我使用了两个线程。一个线程使用计时器连续调用 redirectConsoleLogToDocumentFolder 方法。其他线程用于在循环中运行一些 sql 查询并添加一些 NSLog 条目。一段时间后,我收到文件已加密或不是数据库错误消息。

作为修复,我删除了 applicationDidBecomeActive: 方法中的 redirectConsoleLogToDocumentFolder 方法调用,并将其保留在 didFinishLaunchingWithOptions: 方法中,以保证修复到期原因如下。

  1. 当应用程序开始运行时,日志文件已经关闭。
  2. 只有一个线程处于事件状态(主线程是 main)。
  3. 日志文件打开是顺序过程。

关于ios - 当应用程序变为事件状态时,文件已加密或不是数据库消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22609143/

相关文章:

ios - 从字符串中获取 NSDate 对象

ios - iPhone Simulator有时慢,有时快

ios - 在dispatch_async主队列中尝试saveContext获取核心数据时崩溃

ios - 使用 xcodebuild 命令从 Cordova 项目创建 IPA

ios - #import "Project-Swift.h"出现了一些奇怪的问题

ios - [__NSArrayM objectAtIndex :]: index 9223372036854775807 beyond bounds [0 . 。 13]'

ios - 退出全屏后 MPMoviePlayerController 在 ios 中将缩放模式设置为 MPMovieScalingModeFill

iphone - 检测 iPod 库是否使用 iTunes Match

ios - 隐藏的状态栏拦截 iPad 上的触摸

iphone - TouchDown、TouchUpInside、TouchUpOutside、TouchCancel 事件的顺序是什么?