iPhone上的SQLite表无效?

iPhone上的SQLite表无效?,iphone,objective-c,cocoa-touch,ios,sqlite,Iphone,Objective C,Cocoa Touch,Ios,Sqlite,我一直试图通过我的iphone访问SQLite3数据库,但我一直没有得到这样的表:user\u info作为一个错误 以下是我所经历的步骤: 通过命令行创建数据库: sqlite3 users.sqlite 创建表格用户信息名称文本、信息文本; 插入用户信息值'Name1','这是Name1'的信息; 从用户信息中选择*; [结果]:名称1 |这是名称1的信息 从sqlite_master中选择*; [结果]:表格|用户信息|用户信息| 3 |创建表格用户信息名称文本,信息文本 将其复制到XCo

我一直试图通过我的iphone访问SQLite3数据库,但我一直没有得到这样的表:user\u info作为一个错误

以下是我所经历的步骤:

通过命令行创建数据库:

sqlite3 users.sqlite 创建表格用户信息名称文本、信息文本; 插入用户信息值'Name1','这是Name1'的信息; 从用户信息中选择*; [结果]:名称1 |这是名称1的信息 从sqlite_master中选择*; [结果]:表格|用户信息|用户信息| 3 |创建表格用户信息名称文本,信息文本 将其复制到XCode中的resources文件夹中,并选择将其复制到适当的目录中

尝试访问它并获取错误no-this table:user\u info

好的,那我怎么做3?嗯,我已经更新了一点,所以现在我尝试创建不存在的表。这是我目前的代码:

static NSString *dbname = @"users.sqlite";

-(NSString *) dbFilePath {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(
        NSDocumentDirectory, NSUserDomainMask, YES
    );
    NSString *documentsDir = [paths objectAtIndex:0];
    NSString *dbPath = [documentsDir stringByAppendingPathComponent:dbname];
    BOOL success = [fileManager fileExistsAtPath:dbPath];
    if (!success) {
        fprintf(stderr, "Database is not writeable!\n");
    }
    return dbPath;
}

- (void)createEditableCopyOfDatabaseIfNeeded {
    BOOL success;
    NSError *error;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *writeableDBPath = [self dbFilePath];

    success = [fileManager fileExistsAtPath:writeableDBPath];
    if (success) {
        return;
    }

    NSString *defaultDBPath =
        [[[NSBundle mainBundle] resourcePath]
            stringByAppendingPathComponent:dbname];

    success = [fileManager
                    copyItemAtPath:defaultDBPath
                    toPath:writeableDBPath
                    error:&error];

    if (!success) {
        fprintf(stderr, "Failed to create writable database file\n");
    }
}

-(void) openDB {
    if (sqlite3_open([[self dbFilePath] UTF8String], &db) != SQLITE_OK) {
        sqlite3_close(db);
        fprintf(stderr, "Database failed to open.\n");
    }
}

-(void) createTableIfNeeded {
    NSString *result = @"";
    sqlite3_stmt *statement;

    char *sql = sqlite3_mprintf(
        "CREATE TABLE IF NOT EXISTS user_info (name text info text);"
    );

    dbresult = sqlite3_prepare_v2(db, sql, strlen(sql), &statement, NULL);
    if (SQLITE_OK != dbresult) {
        NSAssert1(0, "no user_info table!", nil);
        fprintf(
            stderr,
            "Error in preparation of query: %s\n", 
            sqlite3_errmsg(db)
        );
        sqlite3_close(db);
        return;
    }
    sqlite3_finalize(statement);
    sqlite3_free(sql);
}

- (NSString *)getDatabaseEntry:(NSString *)i_name {
    NSString *result = @"";
    sqlite3_stmt *statement;

    char *sql = sqlite3_mprintf(
        "SELECT 'info' FROM 'user_info' WHERE name='%q'",
        [i_name cStringUsingEncoding:NSASCIIStringEncoding]
    );

    dbresult = sqlite3_prepare_v2(db, sql, strlen(sql), &statement, NULL);
    if (SQLITE_OK != dbresult) {
        fprintf(
            stderr,
            "Error in preparation of query: %s\n", 
            sqlite3_errmsg(db)
        );
        sqlite3_close(db);
        return result;
    }
    dbresult = sqlite3_step(statement);
    if (SQLITE_ROW == dbresult) {
        char *nfo = (char *)sqlite3_column_text(statement, 0);
        result = [NSString stringWithUTF8String:nfo];
    }
    sqlite3_finalize(statement);
    sqlite3_free(sql);
    return result;
}

// viewDidAppear
- (void)viewDidAppear:(BOOL)animated {
    [self createEditableCopyOfDatabaseIfNeeded];
    [self openDB];
    [self createTableIfNeeded];
}

// Later, when I have a valid user:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker
        shouldContinueAfterSelectingPerson:(ABRecordRef)person {
    ...
    NSString *nfo = [self getDatabaseEntry:name.text];
    ...
}

这堵墙我已经贴了好几天了,所以非常感谢您的帮助。

好吧,我已经修好了,但我不确定如何修好。 我创建了一个空白项目,并按照教程进行操作: 并确保这一切都有效。是的

然后我使用了这里的钻头: 将数据库复制到可写入的位置。我以前有非常相似的代码

所以现在它起作用了。 我专门用sqlite3扩展构建了一个新表。我不知道这是否真的有区别。 我还使用了:

[[NSBundle mainBundle] pathForResource:@"users" ofType:@"sqlite3"];
与之相反:

[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:dbname];
同样,不知道这是否重要

希望这对其他人有帮助

//----------------------------------------------------------------------------
-(NSString *) dbFilePath {
    NSError *error;
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
                                                         NSUserDomainMask,
                                                         YES);
    NSString *documentsDir = [paths objectAtIndex:0];
    NSString *dbPath = [documentsDir stringByAppendingPathComponent:@"users.sqlite3"];
    BOOL success = [fileManager fileExistsAtPath:dbPath];
    if (!success) {
        fprintf(stderr, "Database is not writeable!  Attempting to create writeable database.\n");
        NSString *bundle_path = [[NSBundle mainBundle] pathForResource:@"users" ofType:@"sqlite3"];
        success = [fileManager copyItemAtPath:bundle_path toPath:dbPath error: &error];
        if (!success) {
            fprintf(stderr, "Failed to create writeable database file\n");
        }
    }
    return dbPath;
}

//----------------------------------------------------------------------------
-(void) openDB {
    if (sqlite3_open([[self dbFilePath] UTF8String], &db) != SQLITE_OK) {
        sqlite3_close(db);
        NSAssert(0, @"Database failed to open.");
        fprintf(stderr, "Database failed to open.\n");
    }
}

//----------------------------------------------------------------------------
- (NSString *)getDatabaseEntry:(NSString *)i_name {
    NSString *result = @"";
    sqlite3_stmt *statement;

    char *sql = sqlite3_mprintf(
        "SELECT info FROM user_info WHERE name='%q'",
        [i_name cStringUsingEncoding:NSASCIIStringEncoding]
    );
    dbresult = sqlite3_prepare_v2(db, sql, strlen(sql), &statement, NULL);
    if (SQLITE_OK != dbresult) {
        fprintf(stderr,
                "Error in preparation of query: %s\n",
                sqlite3_errmsg(db));
        sqlite3_close(db);
        sqlite3_free(sql);
        return result;
    }

    dbresult = sqlite3_step(statement);
    if (SQLITE_ROW == dbresult) {
        char *nfo = (char *)sqlite3_column_text(statement, 0);
        result = [NSString stringWithUTF8String:nfo];
    }
    sqlite3_finalize(statement);
    sqlite3_free(sql);

    return result;
}

只有受虐狂才会在Objective-C中直接使用SQLite C API,或者取而代之。先生,我是受虐狂:我开始研究CoreData接口,但我已经了解SQL和关系数据库,因此从理论上讲,这应该是更快的解决方案。然后查看FMDB。它只是围绕SQLite C API的一个包装器,这样您就可以用本机对象和更类似可可的方式与之交互。@DaveDeLong谢谢Dave,听起来很有趣。GitHub页面上的文档非常简单,粗略的web搜索并没有引起太多关注。对FMDB的教程和文档有什么建议吗?我发现它附带的示例非常简单。如果您有问题,请随时在这里发布。我也可能会写一些文件,然后提交给ccgus的回购协议。