【问题标题】:sqlite fts does not work in adhoc version of app, but only in version started from xcodesqlite fts 在应用程序的临时版本中不起作用,但仅在从 xcode 开始的版本中起作用
【发布时间】:2012-02-07 21:23:30
【问题描述】:

我对 sqlite 有一个奇怪的问题,这让我抓狂。

我已经在我的应用程序中实现了一个 sqlite 数据库,当我通过 xcode 启动应用程序时,一切正常。在模拟器以及我的 ipad 上。 但是,当我构建一个临时版本并在我的 ipad 上安装临时版本时,应用程序崩溃,因为它没有从 sql 数据库中获取任何数据,因为数据库中没有数据。 首次启动时,应用程序应使用从 xml 文件中获取的数据初始化数据库,然后仅通过 sqlite 数据库访问数据。 如果从 xcode 运行,效果很好,但如果从 ad-hoc 版本运行,则效果不佳。

有谁知道为什么会这样以及如何解决这个问题?如果需要源代码,我会提供。

数据库文件包含在包中,即使不包含,也会被创建。

提前谢谢, 小牛1st

现在我在我的 appDidFinishLaunchingWithOptions 中执行此操作

NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];
[AppState sharedInstance].s_databasePath = [documentsDir stringByAppendingPathComponent:[AppState sharedInstance].s_databaseName];



if ([self checkForSQLiteDataBaseFile])
{
    if (![self checkForSQLiteDataBaseTable]) {
        [self loadDataFromXMLIntoNSDictionary];
    }
}

-(BOOL) checkForSQLiteDataBaseFile
{
    BOOL ret = NO;
    // Check if the SQL database has already been saved to the users phone, if not then copy it over
// Create a FileManager object, we will use this to check the status
// of the database and to copy it over if required
    NSFileManager *fileManager = [NSFileManager defaultManager];

// Check if the database has already been created in the users filesystem
// If the database already exists then return without doing anything
    if([fileManager fileExistsAtPath:[AppState sharedInstance].s_databasePath]) 
        {
            Log2(@"databasePath: %@", [AppState sharedInstance].s_databasePath);
            ret = YES;
            return ret;
        }

// If not then proceed to copy the database from the application to the users filesystem

// Get the path to the database in the application package
    NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:[AppState sharedInstance].s_databaseName];

    // Copy the database from the package to the users filesystem
    [fileManager copyItemAtPath:databasePathFromApp toPath:[AppState sharedInstance].s_databasePath error:nil];
    Log2(@"databasePath: %@", [AppState sharedInstance].s_databasePath);

    ret = YES;
    return ret;
}   

这是我的文档路径:databasePath: /var/mobile/Applications/0CE5F143-04AC-4E1C-9A94-2B253F86F854/Documents/KatalogDaten

我还发现,我的数据库是用sqlite打开的,因为下面的说法是正确的:

if(sqlite3_open([[AppState sharedInstance].s_databasePath UTF8String], &database) == SQLITE_OK)

*编辑** 在使用 iExplorer 检查我的 ipad 上的应用程序的文件系统后,我注意到该表确实在那里并且本身也有内容。但是由于我在我的应用程序中处理虚拟表,因为我需要全文搜索,所以如果该数据库中不存在虚拟表并且似乎以某种方式失败,我想创建一个虚拟表。如果我发现更多信息,我会提供进一步的更新。

**编辑***

所以,我想我发现了错误在哪里,但没有找到原因。

以下源代码正常执行,但只返回所需的结果,当从我的 ipad 上的 xcode 运行时,而不是从我的 ipad 上的 ad-hoc 版本运行时。

if(sqlite3_open([[AppState sharedInstance].s_databasePath UTF8String], &database) == SQLITE_OK)
{
    NSLog(@"Database opened successfully!");
    const char *sqlQuery = [@"select DISTINCT tbl_name from sqlite_master where tbl_name = ?;" UTF8String]; 
    Log2(@"sqlquery for selecting distinct table: %s", sqlQuery);
    sqlite3_stmt *compiledQuery;
    if(sqlite3_prepare_v2(database, sqlQuery, -1, &compiledQuery, NULL) == SQLITE_OK) 
    {
        sqlite3_bind_text(compiledQuery, 1, [k_db_virtualTableName UTF8String], -1, SQLITE_TRANSIENT);

        if(sqlite3_step(compiledQuery)) 
        {
            // look if virtual table already exists
            if ((char *)sqlite3_column_text(compiledQuery, 0) == nil) 
            {
                NSLog(@"Create virtual table!");
                sqlite3_finalize(compiledQuery);

                sqlQuery = [[NSString stringWithFormat:@"CREATE VIRTUAL TABLE %@ USING FTS3 (%@);", k_db_virtualTableName, keyString] UTF8String];
                Log2(@"sqlQuery: %s", sqlQuery);        
                if(sqlite3_prepare_v2(database, sqlQuery, -1, &compiledQuery, NULL) == SQLITE_OK) 
                {   
                    NSLog(@"query for virtual table is ok!");
                    if(sqlite3_step(compiledQuery)) 
                    {
                        NSLog(@"query for virtual table was executed properly!");
                        sqlite3_finalize(compiledQuery);
                        [self fillSQLiteDataBaseTable: k_db_virtualTableName WithDataFromDict: [[[xmlDictionary objectForKey:@"UHRENTABELLE"] objectForKey:@"UHR"] mutableCopy]];
                    }
                    else
                    {
                        sqlite3_finalize(compiledQuery);
                    }
                }
            } 
            else
            {
                NSLog(@"Virtual Table already exists!!");
                sqlite3_finalize(compiledQuery);
            }
        }
    }
    else
    {
        NSLog(@"The following statement is not correct: %@", sqlQuery);
    }
}
sqlite3_close(database);

fillSQLiteDataBaseTable 方法在通过 xcode 或 ad-hoc 版本运行时也会正常执行。唯一的区别是,在 ad-hoc 版本中,虚拟表的创建会在应用程序没有告诉我的情况下失败。该应用程序就像什么都没发生一样继续运行,但是当我随后查看 sql 文件时,从 ad-hoc 版本运行时那里没有虚拟表。虚拟表仅在从 xCode 运行时存在。

【问题讨论】:

    标签: objective-c ios ipad sqlite ios5


    【解决方案1】:

    好吧..如果该文件在您的资源包中,请不要在文件上写入..您应该首先在应用程序的文档目录中复制一个空白数据库..然后您应该在该文件中写入..apple sdk 没有如果您签署了应用程序,则允许更改 nsbundle 中的任何内容..

    这是在文档目录中获取数据库路径的方法 -

        NSString *documentsDir = [CommonFunctions documentsDirectory];
    
       databasePath = [[documentsDir stringByAppendingPathComponent:@"yourdatabase.sqlite"] retain];
       [self checkAndCreateDatabase];
    

    获取此路径后,您应该检查数据库是否已经存在(然后确定..),如果不存在,则使用以下函数将空白数据库从 nsbundle 复制到文档目录 -

    //check if database exists else copy
    -(void) checkAndCreateDatabase
    {
       // Check if the SQL database has already been saved to the users phone, if not then copy it over
       BOOL success;
    
       // Create a FileManager object, we will use this to check the status
       // of the database and to copy it over if required
       NSFileManager *fileManager = [NSFileManager defaultManager];
    
       // Check if the database has already been created in the users filesystem
       success = [fileManager fileExistsAtPath:databasePath];
    
       // If the database already exists then return without doing anything
       if(success) return;
    
       // If not then proceed to copy the database from the application to the users filesystem
    
       // Get the path to the database in the application package
       NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"yourdatabase.sqlite"];
    
       // Copy the database from the package to the users filesystem
       [fileManager copyItemAtPath:databasePathFromApp toPath:databasePath error:nil];
    
    }
    

    如果您需要更多帮助,请发表评论。

    【讨论】:

    • 被认为我已经这样做了。我编辑了帖子以添加我为此场景提供的功能。
    【解决方案2】:

    我忘了将以下行添加到我的 sqlite.c 文件的头部

    #define SQLITE_ENABLE_FTS3
    

    所以这基本上是问题所在,当我从 xcode 运行我的版本时。使用了我的包中的 sqlite 版本,它似乎支持 fts3 出于某种原因,我不知道不需要使用该定义启用它。

    我 iPad 上的 sqlite 版本虽然不支持 fts。 所以这可能是我的 sqlite 行为如此奇怪的原因。

    无论如何。现在它运行得非常流畅。

    【讨论】:

    • sqlite.c 文件在哪里...我使用的是 .h 或 .m 扩展名。Xcode 中没有 .c 文件。请让我知道..谢谢..
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 2014-12-17
    • 2022-07-27
    • 1970-01-01
    相关资源
    最近更新 更多