2011-02-07 39 views
5

Tôi hiện đang làm việc với một lớp con NSPersistentDocument sử dụng NSOperation để nhập dữ liệu dưới nền. Theo tài liệu, tôi quan sát số NSManagedObjectContextDidSaveNotification sau khi lưu trong tác vụ nền và truyền thông báo tới NSManagedObjectContext trong luồng chính bằng cách sử dụng -mergeChangesFromContextDidSaveNotification:.Dữ liệu cốt lõi và NSOperation

Mọi thứ hoạt động tốt, nhưng nó thể hiện luồng công việc lạ đối với người dùng đang nhập dữ liệu vào tài liệu mới. Họ cần phải lưu một tài liệu trống trước khi thực hiện việc nhập (nếu không thì -save: không thành công vì tài liệu chưa định cấu hình URL cho NSPersistentStoreCoordinator.) Tôi không thấy cách nào khác ngoài trình hướng dẫn "thiết lập tài liệu mới" đảm bảo rằng -writeToURL:ofType:forSaveOperation:originalContentsURL:error: được gọi trước khi nhập.

Ngoài ra, có vẻ như nhiệm vụ nhập trong nền không bao gồm việc sử dụng NSUndoManager trên chuỗi chính. (Tôi cho rằng không an toàn để chia sẻ trình quản lý hoàn tác của bối cảnh đối tượng được quản lý qua các chủ đề.) Từ quan điểm của người dùng, không có cách nào để hoàn tác tất cả các đối tượng mới được tạo trong khi nhập.

Tôi đã đọc cả Sách hướng dẫn lập trình dữ liệu chính và Marcus Zarra, nhưng tôi vẫn còn mới đối với khía cạnh này của khung. Hy vọng rằng, tôi đã bỏ qua điều gì đó: nếu không, tôi sẽ điều chỉnh ứng dụng của mình theo những hạn chế này (lợi ích của Core Data vượt xa những giới hạn giao diện người dùng này.)

Cảm ơn bạn đã dành thời gian!

-

Dựa trên đề nghị Peter Hosey của dưới đây, tôi đã thêm đoạn mã sau để tạo ra một cửa hàng khăng khăng tạm thời trước khi nhập khẩu:

NSPersistentStoreCoordinator *persistentStoreCoordinator = [self.managedObjectContext persistentStoreCoordinator]; 
if ([[persistentStoreCoordinator persistentStores] count] == 0) { 
    // create an in-memory store to use temporarily 
    NSError *error; 
    NSPersistentStore *persistentStore = [persistentStoreCoordinator addPersistentStoreWithType:NSInMemoryStoreType configuration:nil URL:nil options:nil error:&error]; 
    if (! persistentStore) { 
     NSLog(@"error = %@", error); // TODO: better error handling 
    } 
} 

Sau đó, sau khi một file được chọn trong lưu bảng điều khiển, lưu trữ lâu dài tạm thời được di chuyển đến một cửa hàng SQLite tại URL đã chọn:

- (BOOL)writeToURL:(NSURL *)absoluteURL ofType:(NSString *)typeName forSaveOperation:(NSSaveOperationType)saveOperation originalContentsURL:(NSURL *)absoluteOriginalContentsURL error:(NSError **)error 
{ 
    NSPersistentStoreCoordinator *persistentStoreCoordinator = [self.managedObjectContext persistentStoreCoordinator]; 
    for (NSPersistentStore *persistentStore in [persistentStoreCoordinator persistentStores]) { 
     if (persistentStore.type == NSInMemoryStoreType) { 
      // migrate the in-memory store to a SQLite store 
      NSError *error; 
      NSPersistentStore *newPersistentStore = [persistentStoreCoordinator migratePersistentStore:persistentStore toURL:absoluteURL options:nil withType:NSSQLiteStoreType error:&error]; 
      if (! newPersistentStore) { 
       NSLog(@"error = %@", error); // TODO: better error handling 
      } 
     } 
    } 

    return [super writeToURL:absoluteURL ofType:typeName forSaveOperation:saveOperation originalContentsURL:absoluteOriginalContentsURL error:error]; 
} 
+1

Khi bạn sử dụng máy Mac, bạn có thể sử dụng bộ nhớ trong cửa hàng bộ nhớ không, sau đó chuyển ngữ cảnh để sử dụng kho lưu trữ tệp khi sẵn sàng? Ở trên cũng sẽ giải quyết vấn đề với hoàn tác, như bạn chỉ có thể phân chia với toàn bộ bối cảnh ngăn xếp nếu cần thiết. Có vẻ như trong khi tôi đang viết, mọi người đều viết giống nhau :) – Jonathan

Trả lời

5

Tôi không phải là chuyên gia về Dữ liệu cốt lõi, nhưng từ những gì tôi có thể nói từ tài liệu, bạn sẽ muốn bắt đầu với một cửa hàng trong bộ nhớ cho đến khi người dùng (trong thời gian riêng của họ) lưu tài liệu. Sau đó, gửi điều phối viên a migratePersistentStore:toURL:options:withType:error: message để thay đổi từ cửa hàng trong bộ nhớ sang cửa hàng thực sự bền vững mới.Xem tài liệu đó để biết một số chi tiết cần thiết (đặc biệt là về số phận của cửa hàng bạn di chuyển).

+0

Cảm ơn Peter! Việc di chuyển là phần của câu đố bị thiếu - tôi đã cập nhật bài đăng của mình ở trên. – chockenberry

2

Suy nghĩ đầu tiên của tôi về phần công việc/phần tiết kiệm sẽ là, nếu tồn tại Cửa hàng nt chưa được tạo cho tài liệu, để tạo lưu trữ tạm thời trong bộ nhớ, do đó dữ liệu đã nhập sẽ được lưu vào cửa hàng đó (mặc dù tài liệu/cửa sổ vẫn được đánh dấu là bẩn). Sau đó, khi người dùng lưu tài liệu cho thực, bạn sẽ cấu hình lại điều phối viên để loại bỏ lưu trữ trong bộ nhớ và thay thế nó bằng cửa hàng trên đĩa, vì vậy tất cả các lưu thêm sẽ chuyển sang đĩa.

0

Bạn đã thử thiết lập URL tệp tạm thời khi thiết lập điều phối viên chưa? Bạn sẽ có thể hoàn tác các -mergeChangesFromContextDidSaveNotification: trên chủ đề chính. Không cần phải đăng ký một người quản lý hoàn tác cho MOC trên chủ đề nền.

+0

Giải pháp tốt, tuy nhiên Like Daniel, Peter & Brian cho biết, việc tạo một cửa hàng trong bộ nhớ chỉ đơn giản là gọn gàng hơn, và chưa kể nhanh hơn. Tuy nhiên điều này sẽ phải là một thay thế nếu chúng ta nói về một tập dữ liệu rất lớn. – Jonathan

2

Tôi không quen 100% với nội dung của Mac, nhưng tôi chắc chắn bạn có thể sử dụng cửa hàng lưu trữ trong bộ nhớ trước khi người dùng lưu, sau đó thêm cửa hàng sql/plist sau hành động đó.

Có khả năng tốt hơn có thể là tạo một lưu trữ liên tục trên đĩa trong thư mục tạm thời chuẩn và di chuyển nó khi người dùng nhấp để lưu.

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