iOS 10.3无法打开sqlite db

时间:2017-04-17 18:26:18

标签: ios objective-c sqlite

该应用程序将数据保存在许多不同的类别中,每个类别都有自己的数据库。 当您在类别之间切换时,您关闭/打开一个新的数据库。

问题: 其中一些数据库无法通过sqlite打开,其他数据库使用完全相同的代码按预期工作。

此外,此问题在最新更新(iOS 10.3)之后启动。

获取文件路径:

    -(NSString *) filePath {
    NSString *appGroupId = @"xxx.xxx.extension";
    NSURL *appGroupDirectoryPath = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:appGroupId];
    NSURL *dataBaseURL = [appGroupDirectoryPath  URLByAppendingPathComponent:_detailItem];
    NSString *paths = dataBaseURL.path;   
 return paths;
}

打开数据库:

-(void)openDB {
    if (sqlite3_open([[self filePath] UTF8String], &db) != SQLITE_OK) {
        sqlite3_close(db);
        NSLog(@"error");
    }
    else{
        NSLog(@"Opened");
    }
}

使用此代码打开所有数据库,区别仅在于文件名。 大多数文件名都包含特殊字符,例如åäö。

Filenames/DB Names:
ma värd
ga väg A4

- 这些文件存在于同一文件夹中。

- 两个文件都包含数据,有些列甚至相同。

-Both使用相同的代码

创建

当尝试访问第一个时,我得到一个空DB文件,所有SELECT语句都返回“no such table:table_name”

当尝试访问第二个时,一切都按预期工作。

许多SELECT语句之一:

-(NSString *)antalAsString:(NSString *)typAvAntal {

    NSString *antalMatt = [[NSString alloc] init];
    NSString *sql = [NSString stringWithFormat:@"SELECT sum(antal) FROM '%@'", typAvAntal];
    sqlite3_stmt *statement;
    NSLog(@"sql string: %@", sql);

    const char *err;
    if(sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, &err)==SQLITE_OK)
    {
        while (sqlite3_step(statement)==SQLITE_ROW) {
            char *antal = (char *) sqlite3_column_text(statement, 0);
            if (antal != NULL) {
                antalMatt = [[NSString alloc]initWithUTF8String:antal];

                //....


                }
            }

        }

    else {
        NSLog(@"error: %s", sqlite3_errmsg(db));
    }

    sqlite3_finalize(statement);

    return antalMatt;
}

这怎么可能?在iOS 10.3中,sqlite中的某些内容是否有所改变?

EDIT / UPDATE:

使用NSArray / NSLog查看文件夹中的每个文件,并看到包含特殊字符的每个文件名都已复制到另一种格式。

这2个文件:

Filenames/DB Names:
ma värd
ga väg A4

已成为这4个文件:

 ma va\U0308rd
 ma v\U00e4rd

 ga va\U0308g A4
 ga v\U00e4g A4

当我尝试检查“ma va \ U0308rd”的文件大小时,字符串被转换为“mavärd”,所以我不确定这两个中的哪一个被引用。

NSString *sourcePath = [self filePath];

NSFileManager *fm = [NSFileManager defaultManager];
NSError *Error = nil;
NSArray *sourceFiles = [fm contentsOfDirectoryAtPath:sourcePath error:&Error];
int i = 0;
for (NSString *currentFile in sourceFiles)
{
    if ([fm fileExistsAtPath:[sourcePath stringByAppendingPathComponent:[sourceFiles objectAtIndex:i]]])
    {
        if ([currentFile hasPrefix:@"ma"])
        {

        unsigned long long fileSize = [[fm attributesOfItemAtPath:[sourcePath stringByAppendingPathComponent:[sourceFiles objectAtIndex:i]] error:nil] fileSize];

            NSLog(@"FILE: %@ _______ SIZE: %llu", [sourceFiles objectAtIndex:i], fileSize);
        }
    }
    else {
        NSLog(@"NO FILE EXISTS: %@", currentFile);

    }
    i = i+1;
}

很多问题:

为什么更新会创建重复项?

文件管理员选择哪一个?

Sqlite选择哪一个?

有没有办法将“ma va \ U0308rd”声明为NSString而不将其转换为“mavärd”?

非常感谢帮助。

1 个答案:

答案 0 :(得分:0)

我不知道为什么更新会创建应用程序组文件夹中每个文件的副本。 但是了解到有一种方法可以控制哪个unicode表单与特殊字符一起使用。似乎如果没有指定,系统要么随机选择一个,要么选择它找到的第一个文件,无论哪种形式有。

Apple文档:

> decomposedStringWithCanonicalMapping A string made by normalizing the
> string’s contents using the Unicode Normalization Form D.
> 
> decomposedStringWithCompatibilityMapping A string made by normalizing
> the receiver’s contents using the Unicode Normalization Form KD.
> 
> precomposedStringWithCanonicalMapping A string made by normalizing the
> string’s contents using the Unicode Normalization Form C.
> 
> precomposedStringWithCompatibilityMapping A string made by normalizing
> the receiver’s contents using the Unicode Normalization Form KC.

分解 - 使用字符序列(a + \ U0308 =ä)

precomposed - 为每个字符使用唯一代码(\ U00e4 =ä)

能够通过在这些数据之间切换来保存所有数据,以访问真实的db文件并删除已创建的“假人”。

-(NSString *) filePath {
        NSString *appGroupId = @"xxx.xxx.extension";
        NSURL *appGroupDirectoryPath = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:appGroupId];
        NSURL *dataBaseURL = [appGroupDirectoryPath  URLByAppendingPathComponent:_detailItem];
        NSString *paths = dataBaseURL.path.decomposedStringWithCompatibilityMapping;

     return paths;
    }