Things you might have missed from CoreData

Preview:

Citation preview

Advanced CoreDataCocoaHeads Moscow

Сергей Пронин

Full-stack developer CTO, Senior Dev, Co-Founder App in the Air

Senior DeveloperEmpatika

ПреподавательНИУ-ВШЭДепартамент Программной Инженерии

App in the Air

http://appintheair.mobi/

Advanced CoreData

• CoreData stack set-ups

• High-performance Concurrency

• Migration

• Runtime models

CoreData stack set-ups

Default• Предлагается Xcode при создании проекта

• Самый простой в понимании

• Вся работа проходит через Main (UI) thread

• Подходит для маленьких проектов с примитивным хранением Store

Coordinator

Context Main

Nested Simple• I/O операции делаются асинхронно через PrivateConcurrency context

• Mid-level проекты, где данные нужны в момент доступа

• Стандартный MagicalRecord работает таким образом

• Main thread страдает при больших объемах данных

Context Private

Store

Coordinator

Context Main

Nested Workers• I/O операции делаются асинхронно через PrivateConcurrency context

• Одна из самых популярных сборок вложенных контекстов асинхронности

• Ведет себя лучше, чем Nested Simple на больших объемах

• Изменения из workers все равно проходят через Main

workers

Context Private

Store

Coordinator

Context Main

Context Private

Context Private

High-Performance Concurrent Classic

• I/O операции делаются асинхронно через PrivateConcurrency context

• Ведет себя почти идеально на больших объемах

• Изменения из worker не касаются Main

• Нужно “затягивать” изменения

• Записи из Main синхронны — нужно сохранять большие объемы отдельно

worker

Store

Coordinator

Context Private

Context Main

High-Performance Concurrent Modified

• I/O операции делаются асинхронно через PrivateConcurrency context

• Ведет себя почти идеально на больших объемах

• Изменения из worker не касаются Main

• Нужно “затягивать” изменения через NSManagedObjectContextDidSaveNotification

• Записи Main асинхронны — удобство использования

worker

Context Private

Store

Coordinator

Context Private

Context Main

PerformanceAll Off-main Main

Default 4.2s 0.0s 4.2s

Nestedsimple 18.647s 15.637s 3.010s

Nestedworkers 18.927s 15.85s 3.077s

HP Classic 21.05s 20.9s 0.158s

Материалы

1. The concurrent Core Data Stack

2. Backstage with Nested Managed Object Contexts

3. Concurrent Core Data Stacks – Performance Shootout

4. Не нужно бояться CoreData

Migration

Light-weight migration

NSMigratePersistentStoresAutomaticallyOption: trueNSInferMappingModelAutomaticallyOption: true

• Удаление entity, отношения или атрибута • Переименование с renamingIdentifier • Добавление атрибута • Изменение иерархии

Heavy-weight migration• Все, что не подходит под light-weight миграцию

• Изменение типа атрибута

NSMigrationManager — отвечает за миграцию, принимает две модели (“из” и “в”)

NSMappingModel — хранит набор NSEntityMapping

NSEntityMapping — соотношение двух NSEntityDescription между которыми будет маппинг

NSEntityMigrationPolicy — “политика” миграции, обрабатывает преобразование каждого объекта

NSEntityMappinglet eMapping = NSEntityMapping() eMapping.mappingType = .TransformEntityMappingType eMapping.entityMigrationPolicyClassName = “MyEntityMigrationPolicy" eMapping.sourceEntityName = fromEntity.name eMapping.sourceEntityVersionHash = fromEntity eMapping.sourceExpression = NSExpression(format: MANTRA) eMapping.destinationEntityVersionHash = toEntity.versionHash eMapping.destinationEntityName = toEntity.name

let idMapping = NSPropertyMapping() idMapping.name = "_id" idMapping.valueExpression = NSExpression(format: “FUNCTION($source, \"valueForKey:\", \”_id\")") eMapping.attributeMappings = [idMapping]

mappings.append(entityMapping)

MANTRA ”FETCH(FUNCTION($manager, \"fetchRequestForSourceEntityNamed:predicateString:\", \"\(fromEntity.name)\", \"TRUEPREDICATE\"),FUNCTION($manager, \"sourceContext\"), NO)"

NSMappingModel

let mappingModel = NSMappingModel()

//...

mappingModel.entityMapping = mappings

NSMigrationManagerlet migrationManager = NSMigrationManager( sourceModel: sourceModel, destinationModel: destinationModel)

//...

migrationManager.migrateStoreFromURL(store1URL, type: NSSQLiteStoreType, options: nil, withMappingModel: mappingModel, toDestinationURL: store2URL, destinationType: NSSQLiteStoreType, destinationOptions: nil, error: &error)

NSEntityMigrationPolicysubclass

func createDestinationInstancesForSourceInstance( _ sInstance: NSManagedObject, entityMapping mapping: NSEntityMapping, manager: NSMigrationManager, error: NSErrorPointer) -> Bool {

let dInstance = NSEntityDescription .insertNewObjectForEntityForName(mapping.destinationEntityName, inManagedObjectContext: manager.destinationContext)

for (key, value) in dInstance.entity.propertiesByName { let oldValue = sInstance.valueForKey(key as! String) let convertedValue = convert(oldValue) dInstance.setValue(convertedValue, forKey: key as! String) }

manager.associateSourceInstance(sInstance, withDestinationInstance: dInstance, forEntityMapping: mapping) return true }

Launch Arguments

-com.apple.CoreData.MigrationDebug 1Описывает процесс миграции + ошибки

-com.apple.CoreData.SQLDebug 1 (3)Логгирует настоящие SQL запросы на каждый store

Runtime Models

Runtime models

Advanced caching — write once, use anytime — грамотно написанное runtime построение модели позволяет полностью настраивать store с бекэнда

let entity = NSEntityDescription() entity.name = “Person” //если есть entity.managedObjectClassName = “Person”

var properties = [NSAttributeDescription]() let attribute = NSAttributeDescription() attribute.name = “_id” attribute.optional = false attribute.indexed = true attribute.type = .StringAttributeType properties.append(attribute) //... entity.properties = properties

let model = NSManagedObjectModel() model.entities = [entity] let coordinator = NSPersistentStoreCoordinator( managedObjectModel: model)

Материалы

1. Simple Core Data model in Runtime

2. Generating Registered Runtime Classes

3. Mike Ash Blog: Runtime Ambassador

Key Points

• Экспериментировать со сборками CoreData стеков, чтобы найти удачный вариант

• Сложная миграция — это просто

• Вся CoreData без труда строится в runtime, позволяя делать “гибкие” модели с бекенда

Курс НИУ ВШЭ — Swift

Идёт прямо сейчас. Все материалы на русском языке. https://itunes.apple.com/ru/course/razrabotka-ios-prilozenij/id941293188?l=en

iTunes U

Спасибо!

@spronin sergey@pronin.me

Recommended