2011-04-25 165 views
0

首先,我想道歉启动多个关于这个问题的线程,但我已经采取了一步一步的方法和步骤来解决这个非常恼人的问题。我已经花了四天时间来尝试解决这个问题。无法从核心数据提取数据sqlite数据库

情况:我有一个应用程序,我通过Core Data使用预填充的sqlite数据库(106k)。我已经将sqlite数据库移动到Resources文件夹并能够将其复制到文档中。当我测试我可以看到该文件存在,请参阅下面的代码示例和NSLog。

我在委托中使用了示例代码,请参见下文。

一切工作完美的模拟器,但不是当我在设备上测试。

这里是从委托的代码:

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 
if (persistentStoreCoordinator_ != nil) { 
    return persistentStoreCoordinator_; 
} 


NSString *storePath = [[self applicationDocumentsDirectory]  stringByAppendingPathComponent: @"FamQuiz_R0_1.sqlite"]; 
/* 
Set up the store. 
For the sake of illustration, provide a pre-populated default store. 
*/ 
NSFileManager *fileManager = [NSFileManager defaultManager]; 
// If the expected store doesn't exist, copy the default store. 
if (![fileManager fileExistsAtPath:storePath]) { 
    NSString *defaultStorePath = [[NSBundle mainBundle] pathForResource:@"FamQuiz_R0_1"  ofType:@"sqlite"]; 
    if (defaultStorePath) { 
     [fileManager copyItemAtPath:defaultStorePath toPath:storePath error:NULL]; 
    } 
} 

NSURL *storeUrl = [NSURL fileURLWithPath:storePath]; 

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil]; 
persistentStoreCoordinator_ = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel: [self managedObjectModel]]; 

NSError *error; 
if (![persistentStoreCoordinator_ addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeUrl options:options error:&error]) { 
    // Update to handle the error appropriately. 
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    exit(-1); // Fail 
}  

return persistentStoreCoordinator_; 
} 

下面是代码当我读取数据库:

- (void)createQuestionsList: (NSMutableArray *)diffArray { 
NSLog(@">>createQuestionsList<<"); 

NSFileManager *filemgr = [NSFileManager defaultManager]; 
NSString *docsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
NSString *filePath = [docsDirectory stringByAppendingPathComponent:@"FamQuiz_R0_1.sqlite"]; 
if ([filemgr fileExistsAtPath: filePath ] == YES) 
    NSLog (@"\n\n\nFile exists in createQuestionList\n\n\n"); 
else 
    NSLog (@"\n\n\nFile not foundin createQuestionList\n\n\n"); 

int nrOfQuestions = [[diffArray objectAtIndex:0]intValue]; 
int nrOfEasyPlayers = [[diffArray objectAtIndex:1]intValue]; 
int nrOfMediumPlayers = [[diffArray objectAtIndex:2]intValue]; 
int nrOfHardPlayers = [[diffArray objectAtIndex:3]intValue]; 
int nrOfPlayers = nrOfEasyPlayers + nrOfMediumPlayers + nrOfHardPlayers; 

allHardArrayQ = [[NSMutableArray alloc]init]; 
allMediumArrayQ = [[NSMutableArray alloc]init]; 
allEasyArrayQ = [[NSMutableArray alloc]init]; 
allDummyQ = [[NSMutableArray alloc]init]; 
allJointQ = [[NSMutableArray alloc]init]; 
hardQ = [[NSMutableArray alloc]init]; 
mediumQ = [[NSMutableArray alloc]init]; 
easyQ = [[NSMutableArray alloc]init]; 

masterQuestionsArray = [[NSMutableArray alloc] initWithObjects: 
         [NSNumber numberWithBool:[[diffArray objectAtIndex:4]boolValue]], 
         [NSNumber numberWithInt:nrOfHardPlayers], 
         [NSNumber numberWithInt:nrOfMediumPlayers], 
         [NSNumber numberWithInt:nrOfEasyPlayers], 
         [NSNumber numberWithInt:nrOfQuestions], 
         nil]; 
NSLog(@"masterQuestionsArray %@", masterQuestionsArray); 

NSError *error; 

//=========PREPARE CORE DATA DB===========// 
if (managedObjectContext == nil) { managedObjectContext = [(FamQuiz_R0_1AppDelegate *) 
                  [[UIApplication sharedApplication] delegate] managedObjectContext]; } 

// Define qContext 
NSManagedObjectContext *qContext = [self managedObjectContext]; 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entity = [NSEntityDescription 
           entityForName:@"questions" inManagedObjectContext:qContext]; 
[fetchRequest setEntity:entity]; 

NSArray *fetchedObjects = [qContext executeFetchRequest:fetchRequest error:&error]; 
for (NSManagedObject *info in fetchedObjects) { 
    if ([[info valueForKey:@"qDiff"] intValue] == 1) { 
     [allEasyArrayQ addObject:[info valueForKey:@"idQ"]]; 
    } else if ([[info valueForKey:@"qDiff"] intValue] == 2) { 
     [allMediumArrayQ addObject:[info valueForKey:@"idQ"]]; 
    } else if ([[info valueForKey:@"qDiff"] intValue] == 3) { 
     [allHardArrayQ addObject:[info valueForKey:@"idQ"]]; 
    } 
} 

NSLog(@"allEasyArrayQ %@", allEasyArrayQ); 
NSLog(@"allMediumArrayQ %@", allMediumArrayQ); 
NSLog(@"allHardArrayQ %@", allHardArrayQ); 

这里是输出:

2011-04-25 19:35:45.008 FamQuiz_R0_1[963:307] >>createQuestionsList<< 
2011-04-25 19:35:45.021 FamQuiz_R0_1[963:307] 


File exists in createQuestionList 


2011-04-25 19:35:45.031 FamQuiz_R0_1[963:307] masterQuestionsArray (
1, 
0, 
0, 
1, 
5 
) 
2011-04-25 19:35:45.238 FamQuiz_R0_1[963:307] allEasyArrayQ (
) 
2011-04-25 19:35:45.246 FamQuiz_R0_1[963:307] allMediumArrayQ (
) 
2011-04-25 19:35:45.254 FamQuiz_R0_1[963:307] allHardArrayQ (
) 
2011-04-25 19:35:45.311 FamQuiz_R0_1[963:307] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSMutableArray objectAtIndex:]: index 0 beyond bounds for empty array' 

我真的感谢所有帮助,我可以得到解决这个非常令人沮丧的问题:-)

UPDATE

我放在一个的NSLog在委托检查storeURL,并得到了外部iPhone设备上运行时,下面的结果:

storeURL: file://localhost/var/mobile/Applications/7F5FDB03-0D22-46BC-91BC-4D268EB4BBEB/Documents/FamQuiz_R0_1.sqlite 

以下就是当我运行模拟器,没有外部iPhone设备:

storeURL: file://localhost/Users/PeterK/Library/Application%20Support/iPhone%20Simulator/4.2/Applications/E27EC1A4-3A87-4A1B-97DE-D464679005BE/Documents/FamQuiz_R0_1.sqlite 
+0

贵NSError *错误表明什么问题? – NWCoder 2011-04-25 17:47:56

+0

不,它显示没有问题 – PeterK 2011-04-25 18:18:03

+0

你可以发布整个事情; createQuestionsList?它看起来像是在你粘贴的最后一行之后抛出异常...... – lithium 2011-04-26 00:43:24

回答

0

问题解决了

又一个晚上花费试图调试的每一行代码后,不理解,我下载了“iPhone资源管理器”,并手动删除数据库的两个实例直接在设备上和后它终于奏效了。

我注意到数据库没有复制到文档文件夹,那里有一个空的数据库驻留的数据库比填充的数据库小。

现在这两个数据库实例都是正确的:-) ...意味着现在复制工作。

如果你想在“iPhone浏览器”,你会发现它在这里:http://www.macroplant.com/iphoneexplorer/

0

好像你没有从上下文中获取任何东西,所有三个数组都打印为空。这个异常似乎是从你粘贴在这里的东西中抛出的。坦率地说,有不相干的,多余的部分,比如;

//=========PREPARE CORE DATA DB===========// 
if (managedObjectContext == nil) { managedObjectContext = [(FamQuiz_R0_1AppDelegate *) 

...这是从来没有使用过,但主要问题是,我猜,你试图访问一个空数组假设的东西从上下文来在那里,但显然不是...

你应该一步一步地尝试,并确保你的上下文操作返回任何东西... 并清理代码有点让你可以看到问题更容易,或任何人试图帮助你...

1

您收到的崩溃不是来自发布的代码。代码的最后一行是:

NSLog(@"allHardArrayQ %@", allHardArrayQ); 

...打印。

某处从所提供的代码行您拨打一个电话这样的:

[someArray objectAtIndex:0] 

...而someArray是空的,并且会导致超出范围的错误。最有可能的,someArray是刚刚记录的三个空数组之一,但不一定。

您的数组显示为空,因为(1)您没有从您的提取中获得回报,或者(2)qDiffidQ的值不是您认为的值或位置。要确认,请添加日志:

NSArray *fetchedObjects = [qContext executeFetchRequest:fetchRequest error:&error]; 
NSLog(@"fetchedObjects =",fetchedObjects); 
for (NSManagedObject *info in fetchedObjects) { 
    NSLog(@"[info valueForKey:@"qDiff"]",[info valueForKey:@"qDiff"]); 
    NSLog(@"[info valueForKey:@"idQ"]",[info valueForKey:@"idQ"]]); 
    if ([[info valueForKey:@"qDiff"] intValue] == 1) { 
     [allEasyArrayQ addObject:[info valueForKey:@"idQ"]]; 
    .... 

......那么告诉你,如果你是首先获取数据的话。如果没有,那么你需要看看你的核心数据堆栈的配置。

更一般地说,我认为你的代码表明你还没有完全理解掌握核心数据。相反,你似乎试图将Core Data作为一个围绕SQL的轻量级对象包装。这是SQL中熟练使用者的一个常见误解,但是对于Core Data来说却是一个新问题,并且会导致很多设计问题。

首先,在初始化持久性存储后,没有理由检查存储文件的物理存在。内存中的NSPersistentStore对象在没有存储文件的情况下不能存在,因此如果对象存在,文件始终存在。其次,你在数组的形式上堆积了很多额外的数据结构。处理原始SQL时这是一个常见需求,但在使用Core Data时几乎总是不必要的。核心数据的整个要点是手动管理数据(将其保存到磁盘只是一个选项,并不是必需的)。所有数组都应该很可能是数据模型中的实体,您应该使用提取和排序来提取根据任何特定视图的直接需求订购特定的数据。

看到具有强大的SQL或类似背景的人在做某种事情比实现核心数据所需的工作量更为普遍。这就像是一个人驾驶一年的手动变速器切换到自动变速器。他们继续踩在不存在的离合器上,摆弄换档。

+0

TechZen a BIG谢谢你的回答,我将尽快开始工作。然而,一切工作都在模拟器中完美运行,但是当我移动到iPHONE设备时并非如此。我的结论是,无论是数据库是空的,资源和模拟器版本中的数据库都是106k,或者我没有指向数据库,我在de设备中的文档文件夹。 – PeterK 2011-04-25 19:06:46

+0

我添加了NSLog,并在模拟器中都运行良好。当我用iPhone设备运行时,我得到“0”=没有命中。同样,我的感觉是,我没有找到设备上的数据库? – PeterK 2011-04-25 19:24:29

+0

在模拟器上运行OK的原因应该是数据库文件中的遗漏数据。所以你没有在那里得到一个空的数组,但是在设备上,新的数据库是空的,当你试图访问数组时,你会得到异常。它不是模拟器vs设备,它是剩余数据vs空数据库...更仔细地检查它,并在删除数据库文件后尝试 – lithium 2011-04-26 00:47:17