2010-01-26 38 views
55

Tôi đang cố gắng sử dụng dữ liệu lõi theo cách đa luồng. Tôi chỉ muốn hiển thị ứng dụng với dữ liệu đã tải xuống trước đó trong khi tải xuống dữ liệu mới ở chế độ nền. Điều này sẽ cho phép người dùng truy cập vào ứng dụng trong quá trình cập nhật.Ứng dụng đa luồng dữ liệu chính

Tôi có một NSURLConnection tải xuống tệp asyncronously khi sử dụng đại biểu (và hiển thị tiến trình), sau đó tôi sử dụng XMLParser để phân tích cú pháp dữ liệu mới và tạo mới NSManagedObjects trong một ngữ cảnh riêng biệt, với persistentStore riêng và sử dụng một chuỗi riêng biệt .

Vấn đề là việc tạo đối tượng mới trong cùng một ngữ cảnh cũ trong khi hiển thị nó có thể ném ngoại lệ BAD_INSTRUCTION. Vì vậy, tôi quyết định sử dụng một ngữ cảnh riêng biệt cho dữ liệu mới, nhưng tôi không thể tìm ra cách để di chuyển tất cả các đối tượng sang ngữ cảnh khác sau khi hoàn tất.

Paolo aka SlowTree

Trả lời

138

The Apple Concurrency with Core Data documentation là nơi bắt đầu. Đọc nó thật cẩn thận ... Tôi bị cắn nhiều lần bởi những hiểu lầm của tôi!

quy tắc cơ bản là:

  1. Sử dụng một NSPersistentStoreCoordinator mỗi chương trình. Bạn không cần chúng cho mỗi chủ đề.
  2. Tạo một NSManagedObjectContext cho mỗi chủ đề.
  3. Không bao giờ vượt qua một NSManagedObject trên một sợi chỉ đến chủ đề khác.
  4. Thay vào đó, hãy lấy ID đối tượng qua -objectID và chuyển cho chủ đề khác.

More quy tắc:

  1. Hãy chắc chắn rằng bạn lưu các đối tượng vào cửa hàng trước khi đối tượng ID. Cho đến khi được lưu, chúng tạm thời và bạn không thể truy cập chúng từ một chuỗi khác.
  2. Và hãy cẩn thận về các chính sách hợp nhất nếu bạn thực hiện thay đổi đối với các đối tượng được quản lý từ nhiều hơn một chuỗi.
  3. NSManagedObjectContext 's -mergeChangesFromContextDidSaveNotification: là hữu ích.

Nhưng hãy để tôi lặp lại, vui lòng đọc kỹ tài liệu! Nó thực sự đáng giá!

+1

Tôi tìm thấy một ví dụ tuyệt vời của việc sáp nhập các bối cảnh trong CoreDataBooks (mergeChangesFromContextDidSaveNotification). Cảm ơn bạn rất nhiều. Chúc một ngày tốt đẹp. Paolo aka SlowTree – SlowTree

+0

Xin cảm ơn Chúa. Tôi đọc điều này đã giải quyết được vấn đề của tôi. Đã nhập một tập dữ liệu lớn trong chuỗi nền và nhận được vô số ngoại lệ không thể đoán trước. Lập tức ngữ cảnh trong chuỗi nền thay vì truyền qua mặc dù dường như đã sửa lỗi của tôi. – tobyc

+2

Tài liệu này chưa được cập nhật để tận dụng các cải tiến rất quan trọng trong iOS 5 - video tôi liên kết đến trong câu trả lời của tôi giờ đây là một tài liệu tham khảo tốt hơn. – JosephH

2

Tôi hy vọng điều này có thể giúp tất cả mọi người gặp vấn đề khi sử dụng dữ liệu lõi trong môi trường đa luồng.

Hãy xem "Bài hát hàng đầu 2" trong tài liệu về táo. Với mã này tôi lấy "viên thuốc màu đỏ" của Ma trận, và phát hiện một thế giới mới, mà không có lỗi kép miễn phí, và không có lỗi. : D

Hy vọng điều này sẽ hữu ích.

Paolo

p.s. Rất cám ơn Yuji, trong tài liệu bạn đã mô tả ở trên, tôi đã tìm thấy ví dụ đó.

73

Hiện tại [tháng 5 năm 2015] Apple Concurrency with Core Data documentation là tốt nhất, rất gây hiểu nhầm vì nó không bao gồm bất kỳ cải tiến nào trong iOS 5 và do đó không còn hiển thị các cách tốt nhất để sử dụng đồng thời dữ liệu cốt lõi.Có hai thay đổi rất quan trọng trong iOS 5 - ngữ cảnh gốc và các loại đồng thời/luồng luồng mới.

Tôi chưa tìm thấy bất kỳ tài liệu văn bản nào bao quát toàn diện các tính năng mới này, nhưng WWDC 2012 video "Session 214 - Core Data Best Practices" không giải thích rõ tất cả.

Magical Record sử dụng các tính năng mới này và có thể đáng xem.

Thông tin cơ bản thực vẫn giống nhau - bạn vẫn có thể chỉ sử dụng các đối tượng được quản lý mà chủ đề của bối cảnh đối tượng được quản lý của họ được tạo.

Bây giờ bạn có thể sử dụng [moc performBlock:] để chạy mã trên chuỗi phải.

Không cần sử dụng hợp nhấtChangesFromContextDidSaveNotification: nữa; thay vào đó tạo một bối cảnh con để thực hiện các thay đổi, sau đó lưu ngữ cảnh con. Việc lưu ngữ cảnh con sẽ tự động đẩy các thay đổi vào trong bối cảnh gốc, và để lưu các thay đổi vào đĩa chỉ cần thực hiện lưu vào ngữ cảnh gốc trong chuỗi của nó.

Để làm việc này bạn phải tạo ra bối cảnh cha mẹ với một loại đồng thời, ví dụ:

mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 

Sau đó trên sợi nền:

context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType]; 
[context setParentContext:mainManagedObjectContext]; 

<... perform actions on context ...> 

NSError *error; 
if (![context save:&error]) 
{ 
    <... handle error ...> 
} 
[mainManagedObjectContext performBlock:^{ 
    NSError *e = nil; 
    if (![mainContext save:&e]) 
    { 
     <... handle error ...> 
    } 
}]; 
+0

Liên kết WWDC dường như là sai mặc dù .. – Philip007

+7

Ưu đãi cho tối đa -date thông tin. SO nên thực hiện cơ chế để thúc đẩy các câu trả lời liên quan đến phát triển công nghệ mới và giảm bớt những câu trả lời được chấp nhận đã lỗi thời. Cảm ơn bạn đã giới thiệu khuôn khổ Magic Record. Tài liệu của nó trông rất đẹp. Tôi có thể thử lại sau. – Philip007

+0

Trái ngược với đoạn mã của bạn, UIManagedDocument theo mặc định tạo ngữ cảnh gốc của nó trong hàng đợi riêng tư và ngữ cảnh con trong hàng đợi chính. Bất kỳ ý tưởng tại sao Apple làm như vậy? Nó hoàn toàn tùy ý? – Philip007

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