Chúng tôi đang làm việc trên một ứng dụng cấp doanh nghiệp, sẽ lưu trữ hàng chục nghìn đối tượng với dữ liệu lõi và chúng tôi đang gặp sự cố ở một số mặt trận.Đề xuất thiết kế bối cảnh đối tượng được quản lý dữ liệu lõi
Ứng dụng của chúng tôi có một số hệ thống độc lập hoạt động trên dữ liệu khi cần. Các hệ thống này bao gồm khám phá các mục, tải các mục, đồng bộ hóa và hiển thị giao diện người dùng. Nếu chúng tôi thiết kế phần mềm của chúng tôi một cách chính xác, sẽ có ít hoặc không có xung đột hợp nhất do các hệ thống khác nhau sửa đổi cùng một đối tượng. Mỗi hệ thống có hàng đợi hoạt động riêng, tất cả đều hoạt động trong nền. Chúng tôi muốn giữ tất cả các đối tượng tạo và sửa đổi trong nền để giảm thiểu các vấn đề hiệu suất UI, đặc biệt là trong đoạn đường nối ban đầu, nơi hàng nghìn đối tượng có thể được tạo từ dữ liệu trên máy chủ. Ở đây chúng tôi đã gặp phải một số vấn đề với các nỗ lực thiết kế khác nhau của chúng tôi. Mức tiêu thụ bộ nhớ lớn trong những lần tăng tốc này, và sự phối hợp không chính xác của tất cả các bối cảnh và ngữ cảnh của trẻ em, gây ra các sự cố và sự cố. Chúng tôi đã cố gắng thiết kế dưới đây:
- Một gốc
NSPrivateQueueConcurrencyType
quản lý bối cảnh đối tượng trong đó có một trẻ emNSMainQueueConcurrencyType
ngữ cảnh. Bộ điều khiển kết quả tìm nạp được giao diện người dùng sử dụng ngữ cảnh con này để tìm nạp kết quả từ đó. Từ ngữ cảnh trẻ emNSMainQueueConcurrencyType
, chúng tôi đã tạo một ngữ cảnh conNSPrivateQueueConcurrencyType
, chúng tôi gọi là "savingContext" và mỗi thao tác nền tạo ra ngữ cảnh con của "savingContext" đó, đã thực hiện các thay đổi và cuối cùng là tiết kiệm đến đỉnh. Ban đầu, chúng tôi đã chọn thiết kế này để không phải xử lý các thông báoNSManagedObjectContextDidSaveNotification
từ nhiều ngữ cảnh con khác nhau. Chúng tôi gói mọi cuộc gọi đến các ngữ cảnhNSPrivateQueueConcurrencyType
và truy cập vào các đối tượng vớiperformBlockAndWait:
. Chức năng, thiết kế này được thực hiện. Tất cả các thay đổi và chèn đã được lưu vào cửa hàng liên tục và giao diện người dùng đã được cập nhật với các thay đổi. Điều này, đã giới thiệu hai vấn đề. Một trong số đó là giao diện người dùng bị chậm trễ trong đoạn đường nối vì các thay đổi đã hợp nhất đi qua ngữ cảnh của trẻ emNSMainQueueConcurrencyType
và quan trọng hơn là sử dụng bộ nhớ rất cao trong khi tăng tốc. Chúng tôi sẽ nhấn vào việc sử dụng RAM cấm do không có khả năng gọireset
đệ quy theo ngữ cảnh (vì ngữ cảnh giao diện người dùng chính cũng có) và/hoặc thiếu kiến thức khi gọirefreshObject:mergeChanges:
. Vì vậy, chúng tôi đã đi một con đường khác. - Có hai ngữ cảnh cấp cao nhất được liên kết với điều phối viên cửa hàng liên tục, một
NSPrivateQueueConcurrencyType
để lưu ngữ cảnh con và hiển thịNSMainQueueConcurrencyType
cho giao diện người dùng.NSMainQueueConcurrencyType
nghe các thông báoNSManagedObjectContextDidSaveNotification
từ ngữ cảnhNSPrivateQueueConcurrencyType
chính và hợp nhất chúng trong chuỗi chính. Mỗi thao tác nền tạo ra bối cảnh con của bối cảnhNSPrivateQueueConcurrencyType
chính, cũng với kiểu đồng thời hàng đợi riêng, thực hiện những gì nó thực hiện, thực hiện "lưu sâu" đệ quy, thực hiện lưu trên ngữ cảnh hiện tại, một cuộc gọi đệ quy để lưu sâu vào cha mẹ, cuộc gọi được đặt lại trên ngữ cảnh hiện tại và lưu lại. Bằng cách này, chúng tôi tránh các vấn đề về bộ nhớ, vì các đối tượng đã tạo được phát hành nhanh chóng sau khi lưu. Tuy nhiên, với thiết kế này, chúng tôi đã gặp rất nhiều vấn đề như khóa chết,NSInternalInconsistencyException
ngoại lệ và bộ kiểm soát kết quả được tải xuống không cập nhật giao diện người dùng mặc dù có lưu thông báo cho ngữ cảnhNSMainQueueConcurrencyType
. Điều này cũng gây ra thời gian tải ban đầu trong giao diện người dùng để làm chậm rất nhiều. Trong thiết kế trước đó, bộ điều khiển kết quả tìm nạp trả về kết quả rất nhanh, trong khi điều này có giao diện người dùng bị chặn trong vài giây cho đến khi khung nhìn tải (chúng tôi khởi tạo bộ điều khiển kết quả được tìm nạp trongviewDidLoad
).
Chúng tôi đã thử nhiều thiết kế trung gian, nhưng chúng xoay quanh cùng một vấn đề, sử dụng bộ nhớ rất cao, bộ điều khiển kết quả tìm nạp không cập nhật giao diện người dùng hoặc deadlocks và NSInternalInconsistencyException
ngoại lệ.
Tôi thực sự cảm thấy thất vọng. Tôi không thể nhưng cảm thấy như thể thiết kế của chúng ta quá phức tạp đối với một thứ gì đó khá đơn giản, và nó chỉ là sự thiếu hiểu biết của chúng ta về một số cơ bản đang giết chết chúng ta.
Vì vậy, các bạn sẽ đề xuất điều gì? Bạn sẽ đề xuất sự sắp xếp nào cho bối cảnh của chúng tôi? Làm thế nào chúng ta nên quản lý các bối cảnh khác nhau trong các chủ đề khác nhau? Các phương pháp hay nhất để giải phóng các đối tượng được chèn và đặt lại bối cảnh? Tránh khóa chết? Tất cả sự giúp đỡ sẽ được đánh giá cao vào thời điểm này.
Tôi cũng đã xem các đề xuất cho danh mục MagicalRecords. Được khuyến nghị? Chúng tôi đã đầu tư vào việc sử dụng các loại Dữ liệu cốt lõi, sẽ khó khăn như thế nào khi di chuyển bằng MR?
Tôi gặp sự cố tương tự (kiến trúc một): http://stackoverflow.com/questions/15999932/core-data-break-retain-cycle-of-the-parent-context/16008470 - Loại kiến trúc nào cuối cùng bạn có đi không? Có lời khuyên nào không? – Zyphrax
Chúng tôi có ngữ cảnh chính và bối cảnh gốc của bố mẹ. Nhưng bối cảnh gốc chỉ được sử dụng để tiết kiệm, vì vậy chúng tôi thiết lập lại nó trên mọi lưu. Chúng tôi có vô số vấn đề. Có vẻ như những tính năng mới này của bối cảnh con và cha mẹ không được suy nghĩ tốt và có rất nhiều lỗi vẫn chưa được Apple giám sát. –
Tôi đang hướng tới kiến trúc với một MOC gốc (PrivateQueue) với một MOC con (MainQueue) và giảm bộ nhớ bằng cách thêm '' '[self.managedObjectContext refreshObject: self mergeChanges: NO];' '' call in '' '-didSave''' trong một số ManagedObject của tôi. Điều này phá vỡ chu kỳ giữ lại giữa các mối quan hệ và cho phép tất cả các MOC để deallocate các đối tượng. Chỉ những MOC với NSPrivateQueueConcurrencyType dường như có một vấn đề kỳ lạ là chúng sẽ không giải quyết các đối tượng ngay lập tức mà vào lần lưu/khôi phục tiếp theo. – Zyphrax