0

我正在使用下面的代码在一个类中创建 db 并在 viewController 中使用它,并在 newViewController 的另一个类中再次使用相同的代码。
这是正确的吗 ?或者如果存在现有数据库,它是否会在其位置创建新数据库或使用?

还是我只需要使用路径?

当我在下面的示例中尝试extern NSString *path时,我收到了中文信件并且无法打开它。

基本上在第二个控制器中,我只读取数据。
所以我试图通过路径访问数据库,打开路径和数据库的数据库。

如果我使用下面的代码创建它并且我想从另一个视图控制器第二次打开它,该怎么做。
请帮忙。
提前致谢。

在第一个控制器中:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docsPath = [paths objectAtIndex:0];
NSString *path = [docsPath stringByAppendingPathComponent:@"test.db"];

FMDatabase *database;
database = [FMDatabase databaseWithPath:path];
[database open];

    [database executeUpdate:@"DROP TABLE IF EXISTS **"];


    [database executeUpdate:@"CREATE  TABLE "];



    //Select query for single row
    FMResultSet *s = [database executeQuery:@"SELECT COUNT(*) FROM table"];
    if ([s next]) {
        int Count = [s intForColumnIndex:0];


    }

 //DO Something

[database close];

上面的代码在 viewcontroller 1 中运行良好。

我在视图控制器 2 中尝试过的东西。它仍然没有用。

extern NSString *path;



    FMDatabase *database;
    database = [FMDatabase databaseWithPath:path];
    [database open];

我在这里得到一个错误,因为路径是看起来像中文的。

错误是EXC_BAD_ACCESS code

还通过以下方式尝试了全球数据库:

extern FMDatabase *database;

并将其用作

[database open];

我仍然得到同样的错误。

最后,它在第二个控制器中使用了以下代码。
我只是想看看这是否是正确的方法,或者我可以使用一些东西作为 db open 。

但我试过了,但它不起作用。另外我没有使用任何错误处理程序,因为我不知道如何在 FMDB 中执行此操作。
提前致谢。

请让我知道以下实现是否正确?:

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
         NSString *docsPath = [paths objectAtIndex:0];
        NSString *newpath = [docsPath stringByAppendingPathComponent:@"test.db"];


          FMDatabase *database2 ;
         database2 = [FMDatabase databaseWithPath:newpath];

         [database2 open];

//DO Something

[database2 close];
4

2 回答 2

2

作为您应该如何检查 FMDB 方法是否成功的示例,下面是一个示例:

#import "FMDatabase.h"
#import "FMDatabaseAdditions.h"

- (void)performDatabaseDemonstration
{
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *docsPath = [paths objectAtIndex:0];
    NSString *path = [docsPath stringByAppendingPathComponent:@"test.db"];

    // open db

    FMDatabase *database = [FMDatabase databaseWithPath:path];
    FMResultSet *rs;

    if ([database open])
    {
        // drop table

        if (![database executeUpdate:@"DROP TABLE IF EXISTS test"])
            NSLog(@"%s: drop error: %@", __FUNCTION__, [database lastErrorMessage]);

        // create table

        if (![database executeUpdate:@"CREATE TABLE test(col1 INTEGER, col2 TEXT)"])
            NSLog(@"%s: create error: %@", __FUNCTION__, [database lastErrorMessage]);

        // insert a row of data

        if (![database executeUpdate:@"INSERT INTO test VALUES(1, 'Rob')"])
            NSLog(@"%s: insert 1 error: %@", __FUNCTION__, [database lastErrorMessage]);

        // insert another row of data

        if (![database executeUpdate:@"INSERT INTO test VALUES(2, 'Rachel')"])
            NSLog(@"%s: insert 2 error: %@", __FUNCTION__, [database lastErrorMessage]);

        // Select query for single row

        if (!(rs = [database executeQuery:@"SELECT count(*) FROM test"]))
            NSLog(@"%s: select error: %@", __FUNCTION__, [database lastErrorMessage]);

        if ([rs next]) {
            int count = [rs intForColumnIndex:0];

            NSLog(@"%s: count = %d", __FUNCTION__, count);
        }

        [rs close];

        // if getting single value from single row, you can use FMDatabaseAdditions.h methods:

        NSInteger count2 = [database intForQuery:@"SELECT col1, col2 FROM test"];
        NSLog(@"%s: count2 = %d", __FUNCTION__, count2);

        // let's actually retrieve data

        if (!(rs = [database executeQuery:@"SELECT col1, col2 FROM test"]))
            NSLog(@"%s: select error: %@", __FUNCTION__, [database lastErrorMessage]);

        while ([rs next]) {
            NSLog(@"%s: col1 = %@; col2 = %@", __FUNCTION__, [rs objectForColumnIndex:0], [rs objectForColumnIndex:1]);
        }

        [rs close];

        //close

        [database close];
    }
    else
    {
        NSLog(@"%s: open error: %@", __FUNCTION__, [database lastErrorMessage]);
    }
}

关于如何从不同的控制器打开数据库,有很多选择。但我可能会建议,除了从两个控制器中检索一些共享路径/文件名变量之外,您可能还希望将文件名以及共享 FMDB 代码实际封装在一个对象中。

就个人而言,每当我发现自己在两个不同的控制器中编写相同或相似的代码时,我都会问自己是否要将该代码抽象到它自己的类中。在这种情况下,例如,与其争论这两个类如何访问数据库文件名,我会创建自己的模型对象(一个NSObject子类),它封装您的 SQL,打开数据库等。然后我可以我的两个视图控制器从该方法对象调用方法,并且真正减少了文件名中的冗余,而且代码本身也是如此。比如创建数据库路径、打开数据库、检查打开是否成功等都是相同的。那么为什么不在某个模型对象中使用一种方法,它可以为您完成所有这些工作。

要使两个控制器都可以访问此模型对象,您有很多选择:

  • 使其成为您的第一个视图控制器的属性,并在 ; 期间将其传递给您的第二个控制器prepareForSegue

  • 为它创建一个单例对象;或者

  • 将其作为您的应用程序委托的属性,您的两个控制器都可以从那里获取它。

于 2013-01-16T14:33:54.177 回答
0

你应该把数据库路径定义为全局变量,第一次使用关闭操作,第二次使用打开的时候,打开数据库,会自动判断是否有数据库,如果没有会自动创建。如果目前,它会直接打开。用你判断数据库是否打开成功: if (! [db open]) { / / error return; } / / some operation / /... [db close];

于 2013-01-16T02:38:10.027 回答