Upgrade to Pro — share decks privately, control downloads, hide ads and more …

История одного мопеда, или как написать FRC* для Mantle

История одного мопеда, или как написать FRC* для Mantle

Uladzimir Burylau

December 12, 2015
Tweet

Other Decks in Programming

Transcript

  1. История одного мопеда, или как написать FRC* для Mantle Бурылов

    Владимир *NSFetchedResultsController "The change tracking and undo management mechanisms are highly optimized and hence intricate and delicate." - NSManagedObjectContext Class Reference
  2. Задача • Отобразить в UI отсортированный список объектов, хранимых в

    БД (CoreData) • Обновлять UI в соответствии с изменениями в базе • Paging
  3. Решение #0 • Изменили БД - уведомили UI явно (NSNotification,

    delegate, etc) • UI перефетчивает список заново • UI затем делает полный reload (UITableView/ UICollectionView) • Optional: UI вычисляет diff и показывает его красиво • Paging: NSFetchRequest limit+offset
  4. Падение производительности • Учащение событий по которым изменяются данные в

    БД и обновляется список • Увеличение количества данных в БД
  5. Запись в БД в фоновом потоке • Background Serial Queue

    для транзакций • На каждую транзакцию новый NSManagedObjectContext • Мерж каждой транзакции в главный контекст синхронно
  6. Разочарования FRC • Плохая работа с limit+offset • Нет возможности

    получить данные об изменениях в конкретном объекте* • Кэш FRC - только для информации о секциях • Мерж в главный контекст все равно медленный :( *в режиме работы на контексте, в который мержат изменения из другого
  7. План революции • Избавиться от NSManagedObject в UI • Избавиться

    от работы с БД в главном потоке • Уведомлять UI о том, что конкретно (какие keypath) изменилось в объекте
  8. Mantle • MTLModel • Plain Old Objective-C Objects • <NSCoding>,

    <NSCopying>, -isEqual:, -hash, - description - бесплатно • MTLManagedObjectAdapter!
  9. Сохранение Mantle в CoreData - проблемы • Дубликация объектов при

    вставке • Невозможность мержа/резолва конфликтов между разными версиями объекта • Проблемы валидации обязательных атрибутов с дефолтным значением в модели CoreData
  10. Чтение Mantle из CoreData - особенности • Циклические ссылки при

    обратных связях • Необходимость автообновления и подписки на изменения одиночного объекта • Необходимость управлять размером дерева зависимостей объектов
  11. Разгрузка главного потока • Отдельный контекст, только для мониторинга изменений

    • Необходимость синхронных, блокирующих мержей • Необходимость особого порядка мержа/ сохранения
  12. Получение изменившихся ключей • NSManagedObject - changedValues • Доступны только

    на том контексте, где были изменения • И только перед сохранением этого контекста
  13. VIBOrderedListController • Содержит FRC на observing контексте • Получение коллбеков

    от FRC • Конвертация NSManagedObject в Mantle • Сбор всех изменений в один пакет и отправка его в RACSignal *updates • ... включая первоначальный фетч и изменения фетч рейнджа
  14. VIBUnsafeUnretainedProxy @implementation VIBOrderedListController! ! ...! ! - (void)dealloc {! _frc.delegate

    = nil;! VIBUnsafeUnretainedProxy *proxy = _frcDelegateProxy;! [_frc.managedObjectContext performBlock:^{! //does not matter, but we need for this block to retain proxy! //so that FRC can complete calling his callbacks to it! proxy.proxiedObject = nil;! }];! }! ! ...! ! @end
  15. Бонус фичи • Буфферинг и мерж (частичный) слишком частых изменений

    (powered by ReactiveCocoa) • Мониторинг изменений в relations (message.contact etc)
  16. FRC workarounds • Плохая работа с limit/offset ...! ! [context

    mergeChangesFromContextDidSaveNotification:notification];! ! for (NSManagedObject *unsafeObj in notification.userInfo[NSUpdatedObjectsKey]) {! //Force the refresh of updated objects which may not have been registered in this context.! NSManagedObject *managedObj = [context existingObjectWithID:unsafeObj.objectID error:NULL];! if (manangedObj != nil) {! [context refreshObject:managedObj mergeChanges:YES];! }! }! ! ...
  17. FRC workarounds • Невалидные сообщения об изменениях • move: 0

    -> 1 + move: 1 -> 0! • move: 0 -> 0 + update: 0! • delete: 0 + delete: 0
  18. VIBModelObserver • Мониторит изменения в базе для отдельного Mantle инстанса:

    • Следит за соответствующим NSManagedObject в observing контексте • NSManagedObjectContextWillSaveNotification NSManagedObjectContextObjectsDidChangeNotificati on • RACSignal *updates • + буфферинг +мерж
  19. TBD • Избавиться от мержа в главный контекст полностью •

    Поддержка секций в VIBOrderedListController • OpenSource? :)