2011-12-30 16 views
13

Tôi đang cố gắng tìm ra cách để tôi có thể tải trước dữ liệu vào dữ liệu cốt lõi trong khi sử dụng UIManagedDocument. nỗ lực của tôi cho đến nay là để làm cho tài liệu trong một ứng dụng "Loader" sử dụng mã này ..Tải trước cơ sở dữ liệu lõi trong iOS 5 với UIManagedDocument

NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory 
                 inDomains:NSUserDomainMask] lastObject]; 
url = [url URLByAppendingPathComponent:@"Default Database"]; 
if(![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]]){ 
    [self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){ 
     if(success)[self loadDataIntoDocument]; 
    }]; 
} 

và sau đó sao chép các tập tin PersistentStore từ thư mục 'tài liệu' đó được tạo ra trong thư mục của giả lập để phần tài nguyên trong Xcode cho ứng dụng chính sẽ sử dụng cơ sở dữ liệu đã tải.

Vấn đề của tôi là tôi không thể tìm ra cách sao chép tài liệu đó từ gói ứng dụng và sử dụng tài liệu đó làm tài liệu thành công.

Tôi đã thử sao chép thư mục tài liệu dưới dạng từ gói ứng dụng và cố gắng truy cập thư mục dưới dạng tài liệu cung cấp lỗi UIManagedDocument chỉ có thể truy cập gói tệp. Tôi đã thử tạo một tài liệu mới trong ứng dụng chính và sao chép persistentStore từ gói trên một tài liệu được tạo trong tài liệu có cùng lỗi. Và tôi đã thử sử dụng phương pháp -(BOOL)loadFromContents:ofType:error: của.. Tôi thậm chí không chắc chắn đây là những gì tôi nên sử dụng.

Có ai có ý tưởng về cách thực hiện việc này thường không? Cảm ơn!

Trả lời

9

Tôi không nghĩ bạn nên tự mình làm rối tung các tệp và thư mục trong iOS.

Bạn có thể mở tài liệu trực tiếp từ gói của mình. Đối với điều đó, bạn chỉ cần sao chép toàn bộ thư mục tài liệu mà bạn đã tạo trong ứng dụng Trình tải vào gói cuối cùng của mình. Cấu trúc nên khá đơn giản, chỉ hai thư mục với tệp persistentStore bên trong.

Sau đó, khi bạn muốn mở tài liệu, bạn cần phải chăm sóc hai điều: bạn cần sử dụng thư mục bó làm thư mục cơ sở và bạn cần thêm / vào cuối tên "tệp" , vì vậy UIManagedDocument biết rằng thư mục là tài liệu. Mã này trông như thế này:

NSURL* url = [[NSBundle mainBundle] bundleURL]; 
url = [url URLByAppendingPathComponent:@"filename/"]; 
UIManagedDocument* doc = [[UIManagedDocument alloc] initWithFileURL:url]; 

Lưu ý rằng bạn không thể ghi vào tập tin đó, như bạn không được phép viết bên trong gói ứng dụng của bạn. Vì vậy, nếu bạn muốn có một tài liệu có thể ghi, bạn cần phải sao chép tài liệu đó vào thư mục tài liệu của bạn. Bạn có thể làm điều đó một cách dễ dàng bằng cách đơn giản tiết kiệm doc đến một vị trí khác nhau:

[doc saveToURL:newURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){}] 

Một điều nữa: Bạn phải chắc chắn rằng các cấu trúc thư mục được tạo ra trong gói ứng dụng của bạn. Cách dễ nhất để thực hiện điều này xảy ra là kéo toàn bộ thư mục vào dự án của bạn và sau đó chọn "Tạo tài liệu tham khảo thư mục cho bất kỳ thư mục được thêm nào". Đối với "tệp" symbollist_en (thực tế là một gói/thư mục), nó sẽ giống như sau:
A folder reference in XCode
Nếu bạn không làm điều này, "nội dung" của tài liệu sẽ nằm trong gói ứng dụng của bạn trực tiếp, không thể mở được dưới dạng UIManagedDocument, như bạn đã phát hiện ra.

4

Câu trả lời của Shezi đã giúp ích rất nhiều nhưng giống như những người khác ở đây: Preloaded Core Data Database in ios5 with UIManagedDocument và tại đây: Pre load core data database coming up black with UIManagedDocument Tôi gặp sự cố.

Thứ nhất, hành vi trên trình mô phỏng có sự khác biệt đáng kể so với hành vi trên thiết bị.Nếu bạn khởi tạo UIManagedDocument bằng cách sử dụng initWithURL nơi URL trỏ đến gói ứng dụng, bạn sẽ nhận được cảnh báo rằng đây là thư mục chỉ đọc trong bảng điều khiển khi chạy trên thiết bị nhưng không có cảnh báo nào xuất hiện trên trình mô phỏng. Xử lý quyền dường như khá khác nhau và bạn có thể nhận được các kết quả khác nhau.

Các tài liệu cho rằng migratePersistentStore:toURL:options:withType:error: nên được sử dụng thay vì [doc saveToURL:newURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){}]

tôi đã dành một thời gian dài cố gắng để có được điều này để làm việc nhưng đã có rất nhiều sự cố khi nhận một con trỏ đến các cửa hàng dai dẳng. Mặc dù ứng dụng của tôi hoạt động tốt cho các hoạt động chỉ đọc sau khi làm theo giải pháp của Shezi, điều phối viên cửa hàng liên tục vẫn tiếp tục cho tôi một con trỏ rỗng cho cửa hàng liên tục. Điều này xảy ra khi tôi thử cả hai – persistentStores (trả về một mảng trống) và – persistentStoreForURL: Nếu có ai đó có thể giải thích tại sao điều này xảy ra, tôi sẽ quan tâm. Điều gây phiền nhiễu là nó đôi khi sẽ làm việc trên giả lập, nhưng khi tôi thử nghiệm trên thiết bị, nó không thành công.

Cuối cùng, tôi đã thay đổi mọi thứ xung quanh và sao chép thư mục gói vào thư mục tài liệu trước tiên, trước khi khởi tạo UIManagedDocument. Điều này dường như đã thực hiện các trick. Đây là mã. Nó giả định rằng UIManagedDocument của bạn là một thuộc tính của lớp. Tôi đặt điều này trong phương thức viewWillAppear của bộ điều khiển xem ban đầu. Hãy nhớ rằng bạn cần phải mở tài liệu nếu bạn khởi tạo bằng cách sử dụng một URL có chứa một kho lưu trữ liên tục hiện có.

if (!self.yourUIManagedDocument) { 
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"yourUIManagedDocument"]; 
    NSString *documentsFolderPath = [documentsDirectory stringByAppendingPathComponent:@"yourUIManagedDocument"]; 

    NSURL *documentsUrl = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
    documentsUrl = [documentsUrl URLByAppendingPathComponent:@"yourUIManagedDocument"]; 

    if (![[NSFileManager defaultManager] fileExistsAtPath:documentsFolderPath]) { 
     NSError *error = nil; 

     if([[NSFileManager defaultManager] copyItemAtPath:bundlePath 
                toPath:documentsFolderPath 
                error:&error]) { 
      self.yourUIManagedDocument = [[UIManagedDocument alloc] initWithFileURL:documentsUrl]; 
      [self.yourUIManagedDocument openWithCompletionHandler:^(BOOL success) { 
      }]; 
     } else { 
      NSLog(@"%@", error); 
     } 
    } else { 
     self.yourUIManagedDocument = [[UIManagedDocument alloc] initWithFileURL:documentsUrl]; 
     [self.yourUIManagedDocument openWithCompletionHandler:^(BOOL success) { 
     }]; 
    } 
} else if (self.yourUIManagedDocument.documentState == UIDocumentStateClosed) { 
    //Document is closed. Need to open it 
    [self.yourUIManagedDocument openWithCompletionHandler:^(BOOL success) { 
    }]; 
} 

Tất nhiên, ở trên giả định rằng bạn đã tạo cơ sở dữ liệu bằng trình mô phỏng và sao chép thư mục vào đúng cách mà Shezi mô tả. Bất kỳ nhận xét hoặc đề xuất nào về cách cải thiện mã đều được chào đón. Tôi vẫn đang học ở đây.

+0

Điều tôi đang làm là tạo thư mục sau (Documents/AppDatabase/StoreContent) trong thư mục tài liệu và chỉ đối phó tệp persistentStore trong thư mục StoreContent. Điều này đang làm việc cho tôi. Bạn có nghĩ rằng tôi sẽ có bất kỳ vấn đề? – tomidelucca

0

Phương pháp của shezi có vẻ phù hợp với tôi, điều duy nhất tôi muốn thêm là "tệp" có nghĩa là symbolist_en trong trường hợp này. Điều này có thể hơi khó hiểu đối với các nhà phát triển mới như tôi (tôi đã đặt persistentStore /).

+0

Cảm ơn bạn đã chỉ ra điều đó, tôi đã chỉnh sửa câu trả lời của mình để phản ánh điều này. – shezi

0

Câu trả lời của Shezi đã giúp ích rất nhiều. Nhưng nó không hoạt động như vậy. Tôi đã bỏ thư mục tài liệu trong xcode nhưng nó không được sao chép từ bó vào thư mục Documents. Sau đó, tôi tình cờ gặp số question của macbeb về việc tải trước. Tôi đã thử phương pháp tiếp cận của mình liên quan đến việc chỉ bao gồm tệp persistentStore trong gói. Sau đó tạo thư mục tên tài liệu được yêu cầu trong thư mục Tài liệu và sau đó sao chép persistentStore vào đường dẫn đó.

Kiểm tra mã bằng nhận xét "COPY FROM BUNDLE"

Tôi đã sử dụng lớp tĩnh để xử lý tài liệu.

+(DocumentHandler *) sharedDocumentHandler { 
    static DocumentHandler *mySharedDocumentHandler = nil; 
    static dispatch_once_t once; 
    dispatch_once(&once, ^{ 
     mySharedDocumentHandler = [[self alloc] init]; 
    }); 
    return mySharedDocumentHandler; 
} 

- (id)init { 
    self = [super init]; 
    if (self) { 
     NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 
     url = [url URLByAppendingPathComponent:@"YourDocumentName"]; 
     self.sharedDocument = [[MyUIManagedDocument alloc] initWithFileURL:url]; 
    } 
    return self; 
} 
- (void)performWithDocument:(OnDocumentReady)onDocumentReady 
{ 
    void (^OnDocumentDidLoad)(BOOL) = ^(BOOL success) { 
     if(success) { 
      onDocumentReady(self.sharedDocument); 
     } else { 
      NSLog(@"Error occured while creating or opening the database"); 
     } 
    }; 

    if (![[NSFileManager defaultManager] fileExistsAtPath:[self.sharedDocument.fileURL path]]) { 
     NSError *error = nil; 

     // COPY FROM BUNDLE 

     NSFileManager *fileManager = [NSFileManager defaultManager]; 

     NSString *DB = [[self.sharedDocument.fileURL path] stringByAppendingPathComponent:@"StoreContent"]; 

     [fileManager createDirectoryAtPath:DB withIntermediateDirectories:YES attributes:nil error:&error]; 

     NSLog(@"create directory error: %@",error); 

     DB = [DB stringByAppendingPathComponent:@"persistentStore"]; 

     NSString *shippedDB = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"persistentStore"]; 

     NSLog(@"%d",[fileManager fileExistsAtPath:shippedDB]); 

     [fileManager copyItemAtPath:shippedDB toPath:DB error:&error]; 

     NSLog(@"Copy error %@",error);   
    } 

    if (![[NSFileManager defaultManager] fileExistsAtPath:[self.sharedDocument.fileURL path]]) { 
     //Create documents [This is required while creating database first time] 
     [self.sharedDocument saveToURL:self.sharedDocument.fileURL 
       forSaveOperation:UIDocumentSaveForCreating 
       completionHandler:OnDocumentDidLoad]; 
    } else if (self.sharedDocument.documentState == UIDocumentStateClosed) { 
     [self.sharedDocument openWithCompletionHandler:OnDocumentDidLoad]; 
    } else if (self.sharedDocument.documentState == UIDocumentStateNormal) { 
     OnDocumentDidLoad(YES); 
    } 
} 
Các vấn đề liên quan