2011-04-25 162 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