2010-01-31 85 views
5

我正在(最後)將我的應用程序加載到iPhone設備上進行測試。到目前爲止,我只在模擬器中測試了應用程序。該應用程序是以數據爲中心的,並使用SQLite數據庫。我創建了一個合適的SQLite數據庫,其中包含我在模擬器中使用的示例數據。我怎樣才能將這個.sqlite3文件複製到實際的iPhone?將數據複製到iPhone上的應用程序數據文件夾中

這是很容易與模擬器,因爲我可以在.sqlite3文件只複製到〜/庫/應用程序支持/ iPhone模擬器/用戶/應用/ {UUID} /文檔文件夾,但我無法弄清楚如何將其轉移到實際iPhone設備上的相同位置。在手機上重新創建數據庫並不是一個真正的選擇,因爲我已經完成了在Mac上創建數據庫的所有硬件。

回答

6

爲什麼不把它添加到你的應用程序包?右鍵單擊Xco​​de中項目窗口中的Resources文件夾,然後選擇Add>Existing Files...以添加您的sqlite數據庫。

你會然後加載從應用程序包文件:

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

感謝Alex。但是,如果它已包含在應用程序包中,我可以回寫到數據庫嗎? – Skoota 2010-01-31 07:11:07

+2

不,但您可以將此「預初始化」基本數據庫從那裏複製到可寫入的「Documents」文件夾。好的是,這種方法還允許用戶「重置」應用程序。 – 2010-01-31 08:02:54

+0

謝謝亞歷克斯。這是一個非常好的方法。 – Skoota 2010-01-31 08:53:29

11

正如亞歷克斯說,你必須增加你的數據庫文件作爲資源到項目中。這將指示Xcode將您的數據庫文件捆綁到.app中。該文件是隻讀的,取決於您將其複製到您的應用程序文檔文件夾(在設備或模擬器上,同樣的事情),基本上它變得可寫。

下面是我用於下面這種事情的代碼。此代碼的好處在於,只要更改.app中捆綁的「主」副本,它就會自動刷新應用程序文檔文件夾中的可寫副本。使用'pathLocal'打開您的(可寫)數據庫...

當操作成功時(無論是否需要複製),下面的函數返回YES。你可以自由地改變與任何適合你:)

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

太棒了。感謝這個代碼卓然。它會讓事情變得更輕鬆一點:)我特別喜歡當主副本更改時代碼將刷新可寫副本。 – Skoota 2010-01-31 09:24:47

0

在這裏,我怎麼做這個創建一個名爲DBManagement 類和M檔實現這些methods.also把此行中實現文件上面@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]; 
} 
} 

使用這些方法,您可以輕鬆地將數據庫加載到應用程序的iphone文檔文件夾中。 抱歉格式化。而appVersionNo是表格中的字段調用versionInfo默認值爲1

相關問題