2010-07-19 27 views
7

Tôi đang phát triển một ứng dụng iPhone có Dữ liệu lõi. Tất cả dữ liệu người dùng phải được đồng bộ hóa với các máy chủ của chúng tôi. Với mục đích này, tôi đã tạo một lớp con của phù thủy NSOperation tải dữ liệu mới từ dịch vụ web của chúng tôi và tạo ra các đối tượng được quản lý tương ứng. Để duy trì mối quan hệ giữa chúng, mọi đối tượng được truyền đi với một remoteID (là khóa chính của DB máy chủ quan hệ).Dữ liệu cốt lõi executeFetchRequest ném NSGenericException (Bộ sưu tập đã bị đột biến khi được liệt kê)

Giả sử có hai đối tượng được quản lý: Bộ < - >> Nhân viên. Đồng bộ hóa hoạt động như sau:

  1. Tải tất cả các phòng ban từ máy chủ. Đối với mỗi bộ phận: tạo một đối tượng Department và thiết lập remoteID của nó.

  2. Tải tất cả nhân viên từ máy chủ. Đối với mỗi nhân viên: tạo đối tượng Employee, tìm nạp bộ phận liên quan (bằng remoteID) và gán nó cho nhân viên.

Tìm nạp bộ phận dẫn đến ngoại lệ sau đây:

*** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSCFSet: 0x69c8a10> was mutated while being enumerated.<CFBasicHash 0x69c8a10 [0x2d6d380]>{type = mutable set, count = 1424, 
entries => <A list of all newly created entities> 

*** Call stack at first throw: 
0 CoreFoundation 0x02d04919 __exceptionPreprocess + 185 
1 libobjc.A.dylib 0x02e525de objc_exception_throw + 47 
2 CoreFoundation 0x02d043d9 __NSFastEnumerationMutationHandler + 377 
3 CoreData  0x026225d0 -[NSManagedObjectContext executeFetchRequest:error:] + 4400 
4 myApp   0x00059de4 +[AppFactory departmentWithRemoteID:inManagedObjectContext:] + 259 

Trường hợp ngoại lệ không được ném mỗi lần. Di chuyển mã vào chuỗi chính sẽ giải quyết được sự cố. Tôi không biết có gì sai. Tôi đã tạo một NSManagedObjectContaxt mới trong luồng đồng bộ hóa và truyền tất cả các đối tượng được quản lý bởi NSManagedObjectID của nó.

Mọi suy nghĩ?

Trả lời

1

Tắt đầu của tôi: Chuỗi "đồng bộ hóa" có thêm đối tượng mới vào bộ sưu tập của Bộ trong khi lặp lại trên chủ đề chính không?

Thông thường, loại ngoại lệ này xảy ra khi bạn đang sửa đổi bộ sưu tập cùng lúc bạn liệt kê bộ sưu tập đó. Trong một kịch bản đa luồng, nó cũng có thể có nghĩa là bộ sưu tập của bạn được liệt kê và cập nhật đồng thời mà không có đồng bộ hóa luồng thích hợp.

+0

với tôi điều này có thể là lý do cho loại vấn đề này. Cách tốt nhất để giải quyết những vấn đề như vậy, bạn có bất kỳ ý tưởng @octy? –

+0

Cảm ơn, một câu trả lời hay cho câu hỏi của bạn đã được cung cấp trong một cuộc thảo luận được liên kết: http://stackoverflow.com/questions/3364769/iphone-nsfetchedresultscontroller-with-delegate-and-data-update-from-a-separate – octy

4

Lỗi "someCollection bị đột biến khi được liệt kê" được gây ra bằng cách thay đổi bộ sưu tập có thể thay đổi tức là mảng, từ điển, bộ, v.v. trong khi điều tra viên đang đi qua nó. Vì bạn không thể liệt kê một mục tiêu di động, điều này sẽ gây ra lỗi.

Trong trường hợp này, lỗi rất có thể là do cố gắng liệt kê mối quan hệ giữa nhân viên của Bộ với chủ đề chính, ví dụ: để hiển thị trong chế độ xem bảng, trong khi chuỗi nền đồng thời thêm nhân viên vào mối quan hệ.

Đã giải quyết vấn đề này, bạn phải đóng băng giao diện người dùng trong khi hợp nhất các thay đổi từ chuỗi nền. Đối với các lần xem bảng, một bộ điều khiển kết quả được tìm nạp (NSFetchedResultsController) với các phương thức ủy nhiệm được triển khai đúng trong bộ điều khiển tableview sẽ xử lý vấn đề một cách độc đáo.

Điều quan trọng là gửi beginUpdates đến chế độ xem trước khi bạn hợp nhất dữ liệu mới. Điều này sẽ cho bảng biết rằng cấu trúc dữ liệu cơ bản của nó đang bị đột biến nên nó sẽ không tự vẽ lại. Khi hợp nhất hoàn tất, hãy gửi endUpdates đến chế độ xem bảng để làm cho nó hiển thị thông tin mới.

+0

Tôi nghĩ về loại vấn đề này và do đó tôi đã tạo hai NSManagedObjectContexts (một cho chủ đề chính và một cho chuỗi đồng bộ). Đó không phải là một giải pháp hợp lệ sao? Tôi cũng sử dụng NSFetchedResultsController cho các lần xem bảng của mình. – Roland

+0

Có, nhưng khi bạn hợp nhất các thay đổi được thực hiện bởi các ngữ cảnh, chúng sẽ kích hoạt nhu cầu cập nhật để phản ánh các thay đổi được thực hiện trong trường hợp khác. Các phương thức ủy nhiệm FRC cho phép bạn yêu cầu giao diện người dùng đóng băng trong khi các thay đổi đó được xử lý. Sau đó, bạn tháo gỡ giao diện người dùng và để cho nó hiển thị các bản cập nhật. Quá trình này thường vô hình đối với người dùng. – TechZen

+0

Ứng dụng gặp sự cố trước khi tôi hợp nhất các thay đổi vào chuỗi chính. – Roland

13

Tôi có cùng sự cố ... Nó đã được giải quyết vì tôi đã sử dụng managedObjectContext đã được tạo trên chuỗi chính trên một chuỗi nền. Giải pháp là tạo một ManagedObjectContext khác nhau trên chuỗi nền và sử dụng persistentStoreCoordinator thường xuyên ... nó hoạt động tốt sau đó!

0

Tôi gặp sự cố tương tự. Bạn có thể sử dụng khóa, mở khóa máy thu. Tôi đã giải quyết vấn đề này cho đến bây giờ.

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