我使用下面的代码在一个类中创建db并在viewController中使用它,并在newViewController中的另一个类中再次使用相同的代码。
这是对的吗 ?或者它是否在其位置创建新数据库或在有现有数据库时使用?
或者我只需要使用路径吗?
当我在下面的示例中尝试extern NSString *path
时,我收到了中文字母,无法打开它。
基本上在第二个控制器中我只读数据 所以我试图通过路径访问数据库,数据库路径和数据库打开。
如果我使用下面的代码创建它并且我想第二次从另一个viewcontoller打开它,该怎么做呢。
请帮忙。
在此先感谢。
在第一个控制器中:
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打开的东西。
但是我尝试了它并且它不起作用。我也没有使用任何错误处理程序,因为我不知道如何在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];
答案 0 :(得分: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
期间将其传递给第二个控制器;
为它创建一个单例对象;或
将其设为您的app delegate的属性,并且您的两个控制器都可以从那里获取它。
答案 1 :(得分:0)
if (! [db open]) {
/ / error
return;
}
/ / some operation
/ /...
[db close];