2012-05-28 4 views
1

iOS 프로그래밍과 코어 데이터가 훨씬 적습니다. 필자가 직관적이지 않은 것은 MATLAB을 사용하여 프로그래밍을 직접 해보았 기 때문에 "스크립팅"언어라고 생각합니다.레코드가 코어 데이터 sqlite 파일에 저장되지 않습니다

어쨌든 내 문제는 내 응용 프로그램 용 데이터베이스를 만들기 위해 무엇을해야하는지 전혀 알 수 없다는 것입니다. 그래서 저는 조금씩 읽고 제 물건의 SQL 데이터베이스를 만든 다음 가져와야한다고 생각했습니다. 간단히 말해서 SQLite db를 만들었고 이미 CoreData 데이터베이스로 가져온 작업을 사용하고 싶습니다.

쉼표로 구분 된 파일 및 xml 파일로 내보내고 그 파일을 읽으려고했지만 그다지 좋지 않았습니다. 그렇게 할 필요가없는 추가 단계처럼 보였습니다.

그래서 SQLite 데이터베이스를 내 리소스로 가져오고 sqlite 프레임 워크를 추가했습니다.

핵심 데이터 모델 설정이 있고 모델의 SQLite 데이터베이스를 백그라운드에서 올바르게 설정하고 있습니다.

개체를 내 엔터티에 추가하기 위해 프로그램을 실행하면 작동하는 것처럼 보이고 나중에 결과를 가져올 수도 있습니다. 그러나 핵심 데이터베이스 SQLite 파일을 검사 할 때 레코드가 저장되지 않았습니다.

어떻게 결과를 가져 오지만 데이터베이스에 저장하지 않을 수 있습니까?

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{ 
//load in the path for resources 
NSString *paths = [[NSBundle mainBundle] resourcePath]; 
NSString *databaseName = @"histology.sqlite"; 
NSString *databasePath = [paths stringByAppendingPathComponent:databaseName]; 
[self createDatabase:databasePath ]; 

NSError *error; 
if ([[self managedObjectContext] save:&error]) { 
    NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]); 
} 

// Test listing all CELLS from the store 
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSEntityDescription *entityMO = [NSEntityDescription entityForName:@"CELL" 
              inManagedObjectContext:[self managedObjectContext]]; 
[fetchRequest setEntity:entityMO]; 
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error]; 
for (CELL *cellName in fetchedObjects) { 
    //NSLog(@"cellName: %@", cellName); 
}  


-(void) createDatabase:databasePath { 
NSLog(@"The createDatabase function was entered."); 
NSLog(@"The databasePath is %@ ",[databasePath description]); 
// Setup the database object 
sqlite3 *histoDatabase; 

// Open the database from filessytem 
if(sqlite3_open([databasePath UTF8String], &histoDatabase) == SQLITE_OK) { 
     NSLog(@"The database was opened"); 
    // Setup the SQL Statement and compile it for faster access 
    const char *sqlStatement = "SELECT * FROM CELL"; 
    sqlite3_stmt *compiledStatement; 

    if(sqlite3_prepare_v2(histoDatabase, sqlStatement, -1, &compiledStatement, NULL) != SQLITE_OK) { 
     NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(histoDatabase)); 
    } 

    if(sqlite3_prepare_v2(histoDatabase, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) { 

     // Loop through the results and add them to cell MO array 
     while(sqlite3_step(compiledStatement) == SQLITE_ROW) { 
      CELL *cellMO = [NSEntityDescription insertNewObjectForEntityForName:@"CELL" inManagedObjectContext:[self managedObjectContext]]; 


      if (sqlite3_column_type(compiledStatement, 0) != SQLITE_NULL) { 
       cellMO.cellName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)]; 
      } else { 
       cellMO.cellName = @"undefined"; 
      } 

      if (sqlite3_column_type(compiledStatement, 1) != SQLITE_NULL) { 
       cellMO.cellDescription = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]; 
      } else { 
       cellMO.cellDescription = @"undefined"; 
      } 

       NSLog(@"The contents of NSString *cellName = %@",[cellMO.cellName description]); 

     } 
    } 


    // Release the compiled statement from memory 
    sqlite3_finalize(compiledStatement); 

} 
sqlite3_close(histoDatabase); 
} 

두 데이터베이스를 모두 열고 닫는 타이밍과 관련이 있다고 생각합니까?

나는

2012-05-28 16:03:39.556 MedPix[34751:fb03] The createDatabase function was entered. 

2012-05-28 16:03:39.557 MedPix[34751:fb03] The databasePath is /Users/jack/Library/Application Support/iPhone Simulator/5.1/Applications/A6B2A79D-BA93-4E24-9291-5B7948A3CDF4/MedPix.app/histology.sqlite 

2012-05-28 16:03:39.559 MedPix[34751:fb03] The database was opened 

2012-05-28 16:03:39.560 MedPix[34751:fb03] The database was prepared 

2012-05-28 16:03:39.575 MedPix[34751:fb03] CoreData: annotation: Connecting to sqlite database file at "/Users/jack/Library/Application Support/iPhone Simulator/5.1/Applications/A6B2A79D-BA93-4E24-9291-5B7948A3CDF4/Documents/MedPix.sqlite" 

2012-05-28 16:03:39.576 MedPix[34751:fb03] CoreData: annotation: creating schema. 

2012-05-28 16:03:39.577 MedPix[34751:fb03] CoreData: sql: pragma page_size=4096 

2012-05-28 16:03:39.578 MedPix[34751:fb03] CoreData: sql: pragma auto_vacuum=2 

2012-05-28 16:03:39.630 MedPix[34751:fb03] CoreData: sql: BEGIN EXCLUSIVE 

2012-05-28 16:03:39.631 MedPix[34751:fb03] CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA' 

2012-05-28 16:03:39.632 MedPix[34751:fb03] CoreData: sql: CREATE TABLE ZCELL (Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, Z_OPT INTEGER, ZCELLDESCRIPTION VARCHAR, ZCELLNAME VARCHAR) 
... 

2012-05-28 16:03:39.669 MedPix[34751:fb03] CoreData: annotation: Creating primary key table. 

2012-05-28 16:03:39.671 MedPix[34751:fb03] CoreData: sql: CREATE TABLE Z_PRIMARYKEY (Z_ENT INTEGER PRIMARY KEY, Z_NAME VARCHAR, Z_SUPER INTEGER, Z_MAX INTEGER) 

2012-05-28 16:03:39.672 MedPix[34751:fb03] CoreData: sql: INSERT INTO Z_PRIMARYKEY(Z_ENT, Z_NAME, Z_SUPER, Z_MAX) VALUES(1, 'CELL', 0, 0) 
... 

2012-05-28 16:03:39.701 MedPix[34751:fb03] CoreData: sql: CREATE TABLE Z_METADATA (Z_VERSION INTEGER PRIMARY KEY, Z_UUID VARCHAR(255), Z_PLIST BLOB) 

2012-05-28 16:03:39.702 MedPix[34751:fb03] CoreData: sql: SELECT TBL_NAME FROM SQLITE_MASTER WHERE TBL_NAME = 'Z_METADATA' 

2012-05-28 16:03:39.703 MedPix[34751:fb03] CoreData: sql: DELETE FROM Z_METADATA WHERE Z_VERSION = ? 

2012-05-28 16:03:39.704 MedPix[34751:fb03] CoreData: sql: INSERT INTO Z_METADATA (Z_VERSION, Z_UUID, Z_PLIST) VALUES (?, ?, ?) 

2012-05-28 16:03:39.705 MedPix[34751:fb03] CoreData: sql: COMMIT 

2012-05-28 16:03:39.710 MedPix[34751:fb03] CoreData: sql: pragma cache_size=200 

2012-05-28 16:03:39.711 MedPix[34751:fb03] CoreData: sql: SELECT Z_VERSION, Z_UUID, Z_PLIST FROM Z_METADATA 

2012-05-28 16:03:39.712 MedPix[34751:fb03] The contents of NSString *cellName = Beta Cell 

2012-05-28 16:03:39.712 MedPix[34751:fb03] The contents of NSString *cellName = Gastric Chief Cell 

... 

2012-05-28 16:03:39.714 MedPix[34751:fb03] The database was prepared 

2012-05-28 16:03:39.764 MedPix[34751:fb03] The createDatabase function has finished. Now fetching. 

2012-05-28 16:03:39.765 MedPix[34751:fb03] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, t0.ZCELLDESCRIPTION, t0.ZCELLNAME FROM ZCELL t0 

2012-05-28 16:03:39.766 MedPix[34751:fb03] CoreData: annotation: sql connection fetch time: 0.0008s 

2012-05-28 16:03:39.767 MedPix[34751:fb03] CoreData: annotation: total fetch execution time: 0.0016s for 0 rows. 

2012-05-28 16:03:39.768 MedPix[34751:fb03] cellName: <CELL: 0x6bbc120> (entity: CELL; id: 0x6bbc160 <x-coredata:///CELL/t57D10DDD-74E2-474F-97EE-E3BD0FF684DA34> ; data: { 
cellDescription = "S cells are cells which release secretin, found in the jejunum and duodenum. They are stimulated by a drop in pH to 4 or below in the small intestine's lumen. The released secretin will increase the s"; 
cellName = "S Cell"; 
organs =  (
); 
specimens =  (
); 
systems =  (
); 
tissues =  (
); 
}) 
... 

섹션은 생략 짧은 절단 터미널 일부 SQL 디버깅 출력을 첨부. 하지만 가져 오기 결과에는 정보가 포함되어 있지만 총 가져 오기 실행은 '0'행에 대한 것입니다. 어떻게 그렇게 될수 있니? 어떤 도움이라도 대단히 감사하겠습니다. 특히 자세한 설명이 필요합니다. :) 감사.

답변

0

새 개체를 모두 삽입 한 후 다시 save:managedObjectContext해야합니다.

많은 새 개체를 삽입하는 경우 프로세스 전체에 주기적으로 저장할 수 있습니다.

2

몇 가지.

먼저 가져 오는 데이터베이스의 크기에 따라 가져 오기를 주 스레드에서 가져오고 싶을 수 있습니다. 그렇지 않으면 applicationDidFinishLaunching : 메소드에있는 동안 오랜 시간이 걸리면 시스템에서 앱을 종료합니다. 다음과 같이이 작업을 수행 할 수 있습니다

// If in applicationDidFinishLaunching, we need to first schedule on the main queue 
// We do this to be one of the first things scheduled once the main queue starts running 
dispatch_async(dispatch_get_main_queue(), ^{ 
    // now get off the main queue 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{ 
     [self createDatabase:databasePath]; 

     // Now put the results back on the main queue 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      NSError *error; 
      if ([[self managedObjectContext] save:&error]) { 
       NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]); 
      } 

     // Test listing all CELLS from the store 
      NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
      NSEntityDescription *entityMO = [NSEntityDescription entityForName:@"CELL" 
             inManagedObjectContext:[self managedObjectContext]]; 
      [fetchRequest setEntity:entityMO]; 
      NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error]; 
      for (CELL *cellName in fetchedObjects) { 
       //NSLog(@"cellName: %@", cellName); 
      } 
     });  

    }); 
}); 

내가 가져 오기가 완료되었는지 여부를 확인하고,하지 않을 경우, 다음 메인 스레드 떨어져 가져 오기 작업을 얻을 그랜드 센트럴 파견을 사용하십시오.

둘째, gerry3이 답변에서 언급했듯이 관리 대상 개체 컨텍스트에 save : 메시지를 보내려고합니다. iOS5의 상위 및 하위 컨텍스트를 사용하면 하위 컨텍스트를 통해 백그라운드로 쉽게 가져온 다음 기본 상위 컨텍스트로 변경 내용을 푸시 할 수 있습니다. 좋은 개요를 보려면 WWDC 2011 핵심 데이터 세션 및 스택 오버플로를 확인하십시오.

// create a child context with a concurrent queue type. 
NSManagedObjectContext *childManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 

// Set the parentContext. Now whenever we save changes to the child context 
// They will be pushed up to the parentContext and we can choose to save or throw them 
// away 
childManagedObjectContext.parentContext=self.managedObjectContext; 

// Loop through the results and add them to cell MO array 
NSInteger rowNumber=0; 
while(sqlite3_step(compiledStatement) == SQLITE_ROW) { 
     CELL *cellMO = [NSEntityDescription insertNewObjectForEntityForName:@"CELL" inManagedObjectContext:[self managedObjectContext]]; 


    if (sqlite3_column_type(compiledStatement, 0) != SQLITE_NULL) { 
     cellMO.cellName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 0)]; 
    } else { 
     cellMO.cellName = @"undefined"; 
    } 

    if (sqlite3_column_type(compiledStatement, 1) != SQLITE_NULL) { 
     cellMO.cellDescription = [NSString stringWithUTF8String:(char *)sqlite3_column_text(compiledStatement, 1)]; 
    } else { 
     cellMO.cellDescription = @"undefined"; 
    } 
    NSLog(@"The contents of NSString *cellName = %@",[cellMO.cellName description]); 

    // Save our records periodically. Choose a good number of iterations on this. 
    // depends on your particular situation. 
    if (rowNumber%100==0){ 
     NSError *mocError=nil; 
     // Save the changes on the child context 
     // This will push the changes up to the parent context. 
     [childManagedObjectContext performBlock:^{ 
      [self.managedObjectContext save: &mocError]; 
      if (mocError){ 
       NSLog(@"mocError on rowNumber: %d, error: %@",rowNumber, error); 
      } 
      // Now save the changes on the parent context 

      [self.managedObjectContext performBlock:^{ 
        NSError *parentMocError=nil; 
        [self.managedObjectContext save: &parentMocError]; 
        if (parentMocError){ 
         NSLog(@"parentMocError on rowNumber: %d, error: %@",rowNumber, parentMocError); 
        } 
      }]; 

     }]; 

    } 
    rowNumber=rowNumber+1; 
} 

// Pickup and stragglers 
[childManagedObjectContext performBlock:^{ 
    [self.managedObjectContext save: &mocError]; 
    if (mocError){ 
     NSLog(@"mocError on rowNumber: %d, error: %@",rowNumber, error); 
    } 
    // Now save the changes on the parent context 

    [self.managedObjectContext performBlock:^{ 
      NSError *parentMocError=nil; 
      [self.managedObjectContext save: &parentMocError]; 
       if (parentMocError){ 
        NSLog(@"parentMocError on rowNumber: %d, error: %@",rowNumber, parentMocError); 
       } 
      }]; 

}]; 

행운을 빕니다 : 위가 코드의 맥락에서

, 당신은 뭔가에게 모든 라인을 할 것입니다!

+0

안녕하세요 팀, 당신의 추천 해 주셔서 감사합니다. 주 스레드를 내리고 자식 부모 컨텍스트를 만드는 것과 같이 제안한 아이디어를 실제로 파고 있습니다. 매우 흥미로운. 나는 그것들을 더 자세히 살펴보고 제안을 구현하려고 노력할 것입니다. 다시 한 번 감사드립니다! :) – esd100

+0

문제 없습니다. 프로젝트에 행운을 빌어 요! – timthetoolman

관련 문제