2010-01-31 13 views
5

Jestem w trakcie (w końcu) ładowanie mojej aplikacji do urządzenia iPhone do testowania. Do tej pory testowałem tylko aplikację w symulatorze. Aplikacja jest zorientowana na dane i wykorzystuje bazę danych SQLite. Stworzyłem odpowiednią bazę danych SQLite z przykładowymi danymi, które wykorzystałem w symulatorze. Jak mogę skopiować ten plik .sqlite3 do rzeczywistego iPhone'a?Kopiowanie danych do folderu Dane aplikacji na iPhone

To było łatwe z symulatorem jak może po prostu skopiować plik .sqlite3 do wsparcia ~/Library/Application/iPhone Simulator/user/Applications/{UUID}/Dokumenty folderu, ale nie mogę dowiedzieć się, jak aby umieścić go w tej samej lokalizacji na urządzeniu iPhone. Odtworzenie bazy danych od zera przez telefon nie jest tak naprawdę opcją, ponieważ wykonałem już wszystkie twarde stocznie, tworząc bazę danych na komputerze Mac.

Odpowiedz

6

Dlaczego nie dodać go do pakietu aplikacji? Kliknij prawym przyciskiem myszy folder Resources w oknie projektu w Xcode, a następnie wybierz opcję Add>Existing Files..., aby dodać bazę danych sqlite.

Będziesz wtedy załadować plik z pakietu aplikacji:

NSString *databasePath = [[NSBundle mainBundle] pathForResource:@"mySQLiteDatabaseFile" ofType:@"sqlite3"]; 
NSData *databaseData = [NSData dataWithContentsOfFile:databasePath]; 
// ... 
+0

Dzięki Alex. Ale czy mogę zapisać do bazy danych, jeśli została ona dołączona do pakietu aplikacji? – Skoota

+2

Nie, ale możesz skopiować "wstępnie zainicjowaną" podstawową bazę danych do folderu "Dokumenty", który można zapisać. Fajną rzeczą jest to, że takie podejście pozwala również użytkownikowi "zresetować" aplikację. –

+0

Dzięki Alex. To bardzo dobre podejście. – Skoota

11

Jak powiedział Alex, trzeba dodać plik bazy danych jako zasób do swojego projektu. Spowoduje to polecenie Xcode do pakowania pliku bazy danych w pliku .app. Ten plik jest jednak tylko do odczytu, od Ciebie zależy, czy skopiujesz go do folderu dokumentów aplikacji (na urządzeniu lub symulatorze, to samo), gdzie zasadniczo jest zapisywalny.

Oto kod, którego używam do tego rodzaju rzeczy poniżej. Zaletą tego kodu jest to, że automatycznie odświeży on zapisywalną kopię w folderze dokumentów aplikacji za każdym razem, gdy zmienisz "główną" kopię zawartą w pliku .app. Użyj "pathLocal", aby otworzyć swoją (zapisywalną) bazę danych ...

Poniższa funkcja zwraca TAK, gdy operacja się powiedzie (bez względu na to, czy kopia była potrzebna, czy nie). Jesteś wolny, aby zmienić to, co pasuje do ciebie :)

NSString *pathLocal, *pathBundle; 

// Automatically copy DB from .app bundle to device document folder if needed 
- (BOOL)automaticallyCopyDatabase { 
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES); 
    NSString *documentsDir = [paths objectAtIndex:0]; 
    pathLocal = [documentsDir stringByAppendingPathComponent:@"mydb.sqlite"]; 
    pathBundle = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"mydb.sqlite"]; 

    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSDictionary *localAttr = [fileManager fileAttributesAtPath:pathLocal traverseLink:YES]; 
    BOOL needsCopy = NO; 
    if (localAttr == nil) { 
     needsCopy = YES; 
    } else { 
     NSDate *localDate; 
     NSDate *appDBDate; 
     if (localDate = [localAttr objectForKey:NSFileModificationDate]) { 
      NSDictionary *appDBAttr = [fileManager fileAttributesAtPath:pathBundle traverseLink:YES]; 
      appDBDate = [appDBAttr objectForKey:NSFileModificationDate]; 
      needsCopy = [appDBDate compare:localDate] == NSOrderedDescending; 
     } else { 
      needsCopy = YES; 
     } 
    } 
    if (needsCopy) { 
     NSError *error; 
     BOOL success; 
     if (localAttr != nil) { 
      success = [fileManager removeItemAtPath:pathLocal error:&error]; 
     } 
     success = [fileManager copyItemAtPath:pathBundle toPath:pathLocal error:&error]; 
     return success; 
    } 
    return YES; 
} 
+0

To fantastyczne. Dzięki za ten kod Zoran. To sprawi, że rzeczy będą trochę (łatwiejsze) dla mnie łatwiejsze :) Szczególnie podoba mi się, że kod odświeży zapisywalną kopię, gdy zmieni się główna kopia. – Skoota

0

tutaj jak ja zrobić to utworzyć klasę o nazwie DBManagement i wm pliku wdrożyć te methods.also umieścić tę linię w pliku wdrażania powyżej linii @implementation

static sqlite3 * CHManagement = nil;

-(NSString *) getDBPath 
{ 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *MyDatabasePath = [documentsDirectory stringByAppendingString:@"/CHManagement.sqlite"]; 
    return MyDatabasePath; 

} 

-(void) checkDataBase 
{ 
NSLog(@"CheckDatabase Called"); 
NSFileManager *fileManager=[NSFileManager defaultManager]; 
NSError *error=[[[NSError alloc]init] autorelease]; 
NSString *dbPath = [self getDBPath]; 
BOOL success=[fileManager fileExistsAtPath:dbPath]; 
if(!success) 
{ 
NSString *defaultDBPath=nil; 
defaultDBPath=[[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:@"CHManagement.sqlite"]; 
success=[fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error]; 
if(!success) 
{ 
    NSAssert1(0,@"failed to create database with message '%@'.",[error localizedDescription]); 
    } 
} 
else 
{ 
sqlite3 *MyDatabase; 
NSInteger VersionNumber=0; 
sqlite3_stmt *CompiledStatement=nil; 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES); 
NSString *documentsDirectory = [paths objectAtIndex:0]; 
NSString *MyDatabasePath = [documentsDirectory stringByAppendingString:@"/CHManagement.sqlite"]; 
if(sqlite3_open([MyDatabasePath UTF8String],&MyDatabase) == SQLITE_OK) 
{ 
    sqlite3_prepare_v2(MyDatabase, "select appVersionNo from VersionInfo", -1, &CompiledStatement, NULL); 
    while(sqlite3_step(CompiledStatement) == SQLITE_ROW) 
    { 
    VersionNumber=sqlite3_column_int(CompiledStatement,0); 
    } 
    sqlite3_reset(CompiledStatement); 
    sqlite3_finalize(CompiledStatement); 
    sqlite3_close(MyDatabase); 
} 
if (VersionNumber!=1) 
{ 
    [self deleteDatabase]; 
    NSString *defaultDBPath=[[[NSBundle mainBundle]resourcePath]stringByAppendingPathComponent:@"CHManagement.sqlite"]; 
    success=[fileManager copyItemAtPath:defaultDBPath toPath:dbPath error:&error]; 
    if(!success) 
    { 
    NSAssert1(0,@"failed to create database with message '%@'.",[error localizedDescription]); 
    } 
    } 
} 
} 

- (void)deleteDatabase 
{ 
NSLog(@"Delete Database Called"); 
NSError **error=nil; 
NSFileManager *FileManager = [NSFileManager defaultManager]; 
NSString *databasepath = [self getDBPath]; 
    BOOL success = [FileManager fileExistsAtPath:databasepath]; 
if(success) { 
[FileManager removeItemAtPath:databasepath error:error]; 
} 
} 

za pomocą tych metod można z łatwością załadować bazę danych do folderu dokumentów iPhone aplikacji. Przepraszamy za formatowanie. i appVersionNo jest polem w tableCalled versionInfo domyślna wartość to 1

Powiązane problemy