2010-01-31 56 views
5

Tôi đang trong quá trình (cuối cùng) tải Ứng dụng của tôi lên thiết bị iPhone để thử nghiệm. Cho đến nay tôi đã chỉ thử nghiệm các ứng dụng trong giả lập. Ứng dụng này tập trung vào dữ liệu và sử dụng cơ sở dữ liệu SQLite. Tôi đã tạo ra một cơ sở dữ liệu SQLite thích hợp với dữ liệu mẫu mà tôi đã sử dụng trong trình mô phỏng. Làm thế nào tôi có thể sao chép tập tin .sqlite3 này vào iPhone thực tế? Điều này thật dễ dàng với trình giả lập vì tôi chỉ có thể sao chép tệp .sqlite3 vào thư mục ~/Library/Application Support/iPhone Simulator/Người dùng/Ứng dụng/{UUID}/Tài liệu, nhưng tôi không thể tìm ra cách để có được điều này vào cùng một vị trí trên thiết bị iPhone thực tế. Việc tái tạo cơ sở dữ liệu từ đầu trên điện thoại không thực sự là một lựa chọn, vì tôi đã thực hiện tất cả các bãi cứng tạo cơ sở dữ liệu trên máy Mac.Sao chép dữ liệu vào thư mục Dữ liệu Ứng dụng trên iPhone

Trả lời

6

Tại sao không thêm nó vào gói ứng dụng của bạn? Nhấp chuột phải vào thư mục Resources trong cửa sổ dự án của bạn trong Xcode, sau đó chọn Add>Existing Files... để thêm cơ sở dữ liệu sqlite của bạn.

Sau đó, bạn sẽ tải các tập tin từ các gói ứng dụng:

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

Cảm ơn Alex. Nhưng tôi có thể viết lại cơ sở dữ liệu nếu nó đã được đưa vào gói ứng dụng không? – Skoota

+2

Không, nhưng bạn có thể sao chép cơ sở dữ liệu cơ bản "đã được khởi tạo" này từ đó vào thư mục 'Documents', có thể ghi được. Điều thú vị là cách tiếp cận này cũng cho phép người dùng "đặt lại" ứng dụng. –

+0

Cảm ơn Alex. Đó là một cách tiếp cận rất tốt. – Skoota

11

Như Alex nói, bạn phải thêm tập tin cơ sở dữ liệu của bạn như một nguồn lực để dự án của bạn. Điều này sẽ hướng dẫn Xcode đóng gói tệp cơ sở dữ liệu của bạn trong tệp .app của bạn. Tuy nhiên, tệp đó là chỉ đọc, tùy thuộc vào bạn để sao chép nó sang thư mục tài liệu ứng dụng của bạn (trên thiết bị hoặc trình mô phỏng, điều tương tự), nơi nó có thể ghi được về cơ bản.

Đây là mã mà tôi sử dụng cho loại điều dưới đây. Những điều tốt đẹp về mã này là nó sẽ tự động làm mới bản sao có thể ghi trong thư mục tài liệu ứng dụng của bạn bất cứ khi nào bạn thay đổi bản sao "chính" đi kèm trong ứng dụng .app. Sử dụng 'pathLocal' để mở cơ sở dữ liệu (có thể ghi) của bạn ...

Hàm bên dưới trả về CÓ khi thao tác thành công (cho dù bản sao có cần thiết hay không). Bạn đang miễn phí để thay đổi điều đó với bất cứ điều gì phù hợp với bạn :)

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

Thật tuyệt vời. Cảm ơn mã Zoran này. Nó sẽ làm cho mọi thứ một chút (tức là rất nhiều) dễ dàng hơn cho tôi :) Tôi đặc biệt thích rằng mã sẽ làm mới bản sao có thể ghi khi bản sao chính thay đổi. – Skoota

0

đây làm thế nào tôi làm điều này tạo ra một lớp gọi là DBManagement và trong tập tin m thực hiện những methods.also đưa dòng này trong tập tin thực hiện trên đường @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]; 
} 
} 

với các phương pháp này bạn có thể dễ dàng tải cơ sở dữ liệu vào thư mục tài liệu iphone của ứng dụng. Xin lỗi về định dạng. và appVersionNo là một trường trong một phiên bản tableCalledInfo giá trị mặc định là 1

Các vấn đề liên quan