fmdb 路径并第二次从另一个 viewController 使用 db
Posted
技术标签:
【中文标题】fmdb 路径并第二次从另一个 viewController 使用 db【英文标题】:fmdb path and using db 2nd time from another viewController 【发布时间】:2013-01-15 21:52:24 【问题描述】:我正在使用下面的代码在一个类中创建 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];
【问题讨论】:
当你在另一个控制器中打开它时,它不会创建一个新的数据库。因此,您如何在一个或另一个控制器中打开/使用肯定存在问题。您必须向我们展示更多代码来诊断问题。您是否检查了所有 FMDB 调用的返回码以确保一切正常运行?例如。您通常会有if (![datatabase2 open]) NSLog("Open failed: %@", [datatabase2 lastErrorMessage]);
和if (![database2 executeUpdate:sql]) NSLog("Execute failed: %@", [datatabase2 lastErrorMessage]);
等。
@Rob 谢谢先生。我已经编辑了上面的代码来解释我正在使用的代码和流程。如果您需要其他任何东西来了解我可能在哪里犯了错误/实施,请告诉我代码。再次感谢先生您的时间和精力。另外,我没有使用所有 FMDB 调用的返回码。因为我不知道该怎么做。
【参考方案1】:
作为您应该如何检查 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
期间将其传递给您的第二个控制器;
为它创建一个单例对象;或
将其设为您的应用委托的属性,您的两个控制器都可以从那里获取它。
【讨论】:
谢谢先生。我有几个查询: NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docsPath = [paths objectAtIndex:0]; NSString *path = [docsPath stringByAppendingPathComponent:@"test.db"]; // open db FMDatabase *database = [FMDatabase databaseWithPath:path]; 如果它不存在,则此代码是否创建 db,但如果它使用它。对 ?因为这就是我在代码中使用的方式。 如果是,那么我将在第一个视图控制器中创建一个方法来检查和创建数据库,并从第二个控制器调用相同的方法,对吧? 如果上述不正确请写代码说明。谢谢。 我还需要使用 [rs close]; 也因为我只使用了 [db close]; 直到现在。我想这可能是错误。你怎么看? @JacobWood 我们超出了原始问题的范围,所以我建议将其迁移到聊天:chat.***.com/rooms/22871/…【参考方案2】:你应该把数据库路径定义为全局变量,第一次使用关闭操作,第二次使用打开,打开数据库,会自动判断是否有数据库,没有会自动create.如果存在,会直接打开。用你判断数据库是否打开成功:
if (! [db open])
/ / error
return;
/ / some operation
/ /...
[db close];
【讨论】:
此外,错误是给出错误说明使用未声明的变量。以上是关于fmdb 路径并第二次从另一个 viewController 使用 db的主要内容,如果未能解决你的问题,请参考以下文章