2013-09-24 2 views
1

내 응용 프로그램 용 SQLite 데이터베이스가 있습니다. db에서 엔터티를 검색하려면 다음과 같이하십시오.objective-c sqlite3 데이터베이스가 변경되지 않습니다.

- (sqlite3*) openDatabaseNamed:(NSString*)databaseName 
{ 
    if(![databaseName isEqualToString:kTopInternationalDatabaseName] && 
     ![databaseName isEqualToString:kTop500RODatabaseName]){ 
     NSAssert(nil, @"Database does not exist!"); 
    } 
    sqlite3 * dataBase; 
    NSString * path; 
    path = [[NSBundle mainBundle] pathForResource:databaseName ofType:@"sqlite3"]; 
    if (sqlite3_open([path UTF8String], &dataBase) != SQLITE_OK) { 
     NSString * errorString = [NSString stringWithFormat:@"[SQLITE] Unable to open database <%@> ",databaseName]; 
     NSAssert(nil,errorString); 
    } 
    return dataBase; 
} 

- (NSArray *) getAllEntitiesForDatabaseNamed:(NSString*)databaseName 
{ 
    (...) 
    sqlite3 * database = [self openDatabaseNamed:databaseName]; 

    NSMutableArray *retval = [[NSMutableArray alloc] init]; 
    NSString *query = [NSString stringWithFormat:@"SELECT * FROM %@",databaseName]; 

    NSArray *properties = [entityClass classProperties]; 

    if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil) 
     == SQLITE_OK) { 
     while (sqlite3_step(statement) == SQLITE_ROW) { 


      for (int i=2; i<countLimit; i++){ 

       chars = (char *) sqlite3_column_text(statement,i+1); 
       if(chars != NULL) 
       { 
        containerString = [NSString stringWithUTF8String:chars]; 
        if(containerString && containerString.length>0){ 
         [entityModel setValue:containerString forKey:properties[i]]; 
        } 
       } 
      } 
      [retval addObject:entityModel]; 
     } 
     sqlite3_finalize(statement); 
    } 
    sqlite3_close(database); 
    return retval.copy; 
} 

모든 것이 예상대로 작동합니다. 엔터티의 사용자 지정 필드를 데이터베이스의 특정 값으로 설정하려면이 메서드를 사용합니다.

- (void)setEntity:(EntityModel *)entity favorite:(BOOL)favorite 
{ 
    NSString *query = [NSString stringWithFormat:@"UPDATE %@ SET favorite = %i WHERE position = '%i';",kDatabaseName,favorite?1:0,entity.positionInTop]; 

    sqlite3_stmt *statement; 
    sqlite3 * database = [self openDatabaseNamed:kTop500RODatabaseName]; 

    if (sqlite3_prepare_v2(database, [query UTF8String], -1, &statement, nil) 
     == SQLITE_OK) { 
     sqlite3_step(statement); 
     sqlite3_finalize(statement); 
    } 
    sqlite3_close(database); 
} 

무슨 일이 일어나고 있는지 조금 이상합니다. 업데이트 방법을 사용하고 getAllEntitiesForDatabaseNamed을 사용하는 모든 항목에 대해 앱 검색어의 동일한주기 내에서 수행 한 변경 사항은 setEntity:Favorite:과 동일하게 유지됩니다. 반면에 업데이트 방법을 사용한 다음 앱을 끄고 다시 시작하면 setEntity:Favorite:을 사용한 변경 사항이 손실됩니다. 왜 그런 생각이 들었 니?

PS : 나는 또한 sqlite3_exec를 사용하려고했지만 결과는 동일합니다

if (sqlite3_exec(database, [query UTF8String], NULL, NULL, NULL) != SQLITE_OK) { 
    // deal with error... 
    NSLog(@" -- ERROR!"); 
} 

답변

4

문제는 당신이에서, 장치에 (읽기 전용 번들에 데이터베이스를 열고있는 것입니다 가장 작은). 대신 데이터베이스가 Documents 폴더에 있는지 확인하고 그렇지 않은 경우 번들에서 데이터베이스를 복사 한 다음 Documents 폴더에서 데이터베이스를 열어야합니다.

따라서, 당신은 같은 것을 할 수 있습니다

NSString *bundlePath = [[NSBundle mainBundle] pathForResource:databaseName ofType:@"sqlite"]; 

NSString *documentsFolder = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0]; 
NSString *documentsPath = [[documentsFolder stringByAppendingPathComponent:databaseName] stringByAppendingPathExtension:@"sqlite"]; 

NSFileManager *fileManager = [NSFileManager defaultManager]; 

if (![fileManager fileExistsAtPath:documentsPath]) { 
    NSError *error = nil; 
    BOOL success = [fileManager copyItemAtPath:bundlePath toPath:documentsPath error:&error]; 
    NSAssert(success, @"%s: copyItemAtPath failed: %@", __FUNCTION__, error); 
} 

그 일을 갖는, 당신은 지금 documentsPath에서 데이터베이스를 열 진행할 수 있습니다.

+0

조금 더 자세하게 설명해 주실 수 있습니까? – Teo

+0

@ 테오. 코드 샘플을 참조하십시오. – Rob

+0

나는 주장이 틀렸고 복사가 성공했을 때 앱을 망칠 것이라고 믿는다. – Teo

관련 문제