понедельник, 16 июля 2012 г.

Core Data. Запрос с сортировкой не любит потоки.

Как известно, Core Data - отличный инструмент для работы с данными большого объема на уровне объектов. Core Data позволяет производить различные операции с контекстами на разных потоках, исходя из правила "один контекст на один поток".
Рядовая ситуация - контекст на главном потоке и "фоновый" контекст на фоновом потоке.
После проведения операция на фоновом потоке и сохранения, назначение sortDescriptors объектам NSFetchRequest не принесет ожидаемого результат. Мне не понятно, чем вызвано такое поведение, но факт остается фактом - использовать массив из NSSortDescriptor объектов для включения сортировки в запрос - тщетное дело. Информации по этому вопросу не очень много, но из того что я смог собрать стало ясно следующее:

  1. Поведение различно на iOS 4 и iOS 5 (iOS 6 не проверял).
  2. Некоторым помогает сохранение главного контекста.
  3. Необходимо следить за тем, чтобы контекст сохранялся на своем потоке. Иными словами, основной контекст всегда будет блокировать интерфейс приложения (поскольку существует на главном потоке).
  4. Если после сохранения контекстов (рекурсивное, сохраняя "фоновые" контексты, "вливая" изменения в основной контекст и сохраняя его в непосредственное хранилище данных) внести изменения в контекст (я добавлял новые объекты), сортировка запроса вновь начнет работать.
  5. Чтобы гарантировано получать сортированный массив можно сортировать массив, получаемый в результате выполнения запроса без сортировки.
  6. NSPredicate работает без проблем. Это прекрасно, потому что он куда важнее NSSortDescriptor (поскольку правильно описанный предикат - это эффективность SQL-запросов).
Кое-что по делу:

Автор смог решить проблему последовательным сохранением контекстов, реализованным в Magical Record. Я долго бился над пробным приложением и мой результат был менее радостным - сортировка не работала.

Более плачевный результат, когда выполнение запроса влекло за собой Bad Access. Автор не приводит код, поэтому есть вероятность, что это дело - результат неаккуратного обращения с памятью. Но тот факт, что сортировка готовых данных проходит без каких-либо ошибок указывает на то, что проблема имеет по крайней мере схожий корень с описанным выше случаем.

Непредсказуемый NSURLConnectionDownloadDelegate

NSURLConnectionDownloadDelegate сменил на посту NSURLDataDelegate () и привнес немало радости iOS-пограммистам, пытавшимся использовать новый делегатный метод – connectionDidFinishDownloading:destinationURL:, потому как получаемый URL указывал на несуществующий файл, в том случае, если файл имел расширение JPG или PDF.
Более подробно на Stackoverflow: