Things you might have missed from CoreData
-
Upload
sergey-pronin -
Category
Technology
-
view
702 -
download
3
Transcript of Things you might have missed from CoreData
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
Материалы
1. Custom CoreData migration
2. Apple Guide: Core Data migration
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 [email protected]