SlideShare a Scribd company logo
Core Data Migrations
and …can we do
better?
Priya Rajagopal
@rajagp
Core Data
Core Data Stack
3
Managed Object
Model (schema)
Persistent Store Coordinator
Managed Object Context (1 ..*)
Managed
Object
Managed
Object
Managed
Object
Persistent
Object Store
(1..*)
Persistent
Store (1..*)
Core Data Stack : iOS10
4
Persistent Container
Managed Object Model
5
• Schema Definition
• Entities , Attributes and Relationships
• Versioning
Image source: https://developer.apple.com/
Schema Changes
6
The Dreaded Persistent Store / Data Model Mismatch
Exception!
7
Option 1 : Delete the app and reinstall
8
Migrations
Option 2: Core Data Migrations
10
Managed Data Model
(Source)
Managed Data Model
(Target)
Source Data
Store
Mapping Model
Target Data
StoreMigration Policy
Case 1
11
Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved.
Source Model
country domain name
University Target Model
country domain name
University
websiteweblink
Lightweight Migrations
12
• Automatic Migrations
• Core Data infers mapping model from source to target model
• Fast
• Handles following Changes
• Simple addition /removal of a new attribute
• A non-optional attribute becoming optional
• An optional attribute becoming non-optional, and defining a default value
• Renaming an entity or property
• Simple Relationship changes
• Simple entity hierarchy changes
• Complete list
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmLightweightMigration.html#//apple_ref/doc/uid/TP40004399-CH4-
SW2
Configure Core Data Stack
13
let persistentStoreDesc = NSPersistentStoreDescription(url: storeUrl)
persistentStoreDesc.shouldMigrateStoreAutomatically = true
persistentStoreDesc.shouldInferMappingModelAutomatically = true
self.persistentContainer?.persistentStoreDescriptions = [persistentStoreDesc]
Some help from editor
14
Case 2
15
Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved.
Source Model
country domain name
University Target Model
University
website
estDate
(Date)
country domain name website
estYear
(String)
Custom Migration Policy
16
// Transform estDate of type Date to estYear of type String
class UniversityDataMigrationPolicy: NSEntityMigrationPolicy {
func transformEstDateToEstYear(_ estDate:NSDate)->String {
let calendar = NSCalendar.current
let components = calendar.dateComponents(Set<Calendar.Component>([.year]), from: estDate as
Date)
return "(components.year!)"
}
}
Define Custom Mapping
17
Custom Mapping
18
Case 3
19
Source Model
country domain name
University Target Model
University
website estYear
name
domain name website estYear
code
country
country
*..1
Custom Migration Policy (1/3)
20
class UniversityMigrationPolicy: NSEntityMigrationPolicy {
override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping:
NSEntityMapping, manager: NSMigrationManager) throws {
// 1. Create destination Instance corresponding to the source instance
let dInstance = NSEntityDescription.insertNewObject(forEntityName: mapping.destinationEntityName!,
into: manager.destinationContext)
let sKeys = sInstance.entity.attributesByName.keys
let sValues = sInstance.dictionaryWithValues(forKeys: Array(sKeys))
let dKeys = dInstance.entity.attributesByName.keys
for dKey in dKeys {
if let matchingValueInSrc = sValues[dKey] {
dInstance.setValue(matchingValueInSrc, forKey: dKey)
}
}
Custom Migration Policy (2/3)
21
let universityName = sValues["name"]
if let countryName = sInstance.value(forKey: "country") as? String {
// 2 . We are tracking the Country managed objects in Migration Manager’s userInfo
// This is to ensure we create a single instance of Country for every countryName
if let userInfo = manager.userInfo , let country = userInfo[countryName] as? NSManagedObject{
// link university entity to country
dInstance.setValue(country, forKey: "country")
}
else {
Custom Migration Policy (3/3)
22
// 3 . Create Country object
let country = NSEntityDescription.insertNewObject(forEntityName: "Country", into: manager.destinationContext)
// Set country name
country.setValue(countryName, forKey: "name")
// 4. Link University object with the corresponding Country object
dInstance.setValue(country, forKey: "country")
// 5. Track the newly created country object in Migration Manager’s userInfo
if let _ = manager.userInfo {
manager.userInfo?[countryName] = country
}
else {
manager.userInfo = [:]
manager.userInfo?[countryName] = country
}
}
// 4. Associate the source with destination instance
manager.associate(sourceInstance: sInstance, withDestinationInstance: dInstance, for: mapping)
}
Custom Mapping
23
Manual
24
let persistentStoreDesc = NSPersistentStoreDescription(url: storeUrl)
persistentStoreDesc.shouldMigrateStoreAutomatically = false
persistentStoreDesc.shouldInferMappingModelAutomatically = false
self.persistentContainer?.persistentStoreDescriptions = [persistentStoreDesc]
• Create Custom Migration Policies
• Create Mapping Models
1. Test if Migration is Needed
25
func isMigrationNeeded()->Bool {
……
let srcMetadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(ofType: NSSQLiteStoreType, at: sourceUrl,
options: nil)
let momPathValue = Bundle.main.path(forResource: "UniversityDataModel", ofType:"momd")
guard let destModel = NSManagedObjectModel(contentsOf: URL(fileURLWithPath: momPathValue)) else { return false }
return destModel.isConfiguration(withName: nil, compatibleWithStoreMetadata: srcMetadata) == false ? true: false
……
}
2. Migrate Stores Progressively
26
func progressivelyMigrate() throws {
// Get the model version that is compatible with the current data store
let idx = try indexOfCompatibleMom(at: sourceUrl, moms: self.models)
let remaining = self.models.suffix(from: (idx + 1))
guard remaining.count > 0 else {
// The stored DB is compatible with the latest model
return // migration not necessary
}
_ = try remaining.reduce(self.models[idx]) { smom, dmom in
do {
try self.migrate(srcStoreUrl: sourceUrl, srcModel: smom, dstModel: dmom)
}
catch {
// handle error
}
return dmom
}
}
3. Identify Model compatible with Store
27
func indexOfCompatibleMom(at storeURL: URL, moms: [NSManagedObjectModel]) throws -> Int {
let meta = try NSPersistentStoreCoordinator.metadataForPersistentStore(ofType: NSSQLiteStoreType, at: storeURL)
guard let idx = moms.index(where: { $0.isConfiguration(withName: nil, compatibleWithStoreMetadata: meta) }) else {
throw MigrationError.IncompatibleModels
}
return idx
}
4. Migrate Store from src to dst model
28
func migrate(srcStoreUrl:URL, srcModel:NSManagedObjectModel,dstModel:NSManagedObjectModel)throws {
// Prepare temp directory for destination
let dir = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString)
try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil)
defer {
_ = try? FileManager.default.removeItem(at: dir)
}
// Perform migration
let mapping = try findMapping(from: srcModel, to: dstModel)
let destURL = dir.appendingPathComponent(srcStoreUrl.lastPathComponent)
let manager = NSMigrationManager(sourceModel: srcModel, destinationModel: dstModel)
try autoreleasepool {
try manager.migrateStore(
from: srcStoreUrl,
sourceType: NSSQLiteStoreType,
options: nil,
with: mapping,
toDestinationURL: destURL,
destinationType: NSSQLiteStoreType,
destinationOptions: nil
)
}
5. Find Mapping Model
29
fileprivate func findMapping(from smom: NSManagedObjectModel, to dmom: NSManagedObjectModel) throws ->
NSMappingModel {
if let mapping = NSMappingModel(from: Bundle.allBundles, forSourceModel: smom, destinationModel: dmom) {
return mapping // found custom mapping
}
// Return inferred mapping model if a custom model not defined.
return try NSMappingModel.inferredMappingModel(forSourceModel: smom, destinationModel: dmom)
}
Core Data Migrations and A Better Option
NoSQL Option for Persisting Data
31
• Non Relational
• Unstructured or Semi Structured Data
• Scalable – both up and down
• SQL-type Queries
Document
• Couchbase
• MongoDB
• DynamoDB
• DocumentDB
Key-Value
• Couchbase
• Riak
• BerkeleyDB
• Redis
• …
Graph
• OrientDB
• Neo4J
• DEX
• GraphBase
Wide Column
• Hbase
• Cassandra
• Hypertable
Data Modeling
32
Data Concern Core Data JSON Document Model (Couchbase)
Rich Structure  Managed Object Model - entities  Documents = containers of related KV pairs
Relationships  Represented  Represented (embed/reference)
Structure Evolution  Migrations
 Flexible
 Dynamic change
Value Evolution  Data can be updated  Data can be updated
Query Interface
 NSFetchRequest
 NSFetchedResultsControllerDelegate
 Query / LiveQuery
JSON to Native Mapping
33
NoSQL: Example 1
Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved.
US Umich.edu
University Of
Michigan US harvard.edu Harvard University -10516645301
{
"type":"university",
"name":"University of Michigan",
"domain":"umich.edu",
"country":"US”
}
{
"type":"university",
"name":"Harvard University”,
"domain":"harvard.edu",
"country":"US",
"estDate":-10516645301
}
NoSQL : Example 2
Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved.
US harvard.edu
Harvard
University
{
"type":"university",
"name":"Harvard University",
"domain":"harvard.edu”,
"country":"US",
"estDate":-10516645301
}
-10516645301
(Double)
US harvard.edu Harvard University “1636”
(String)
{
"type":"university",
"name":"Harvard University",
"domain":"harvard.edu”,
"country":"US",
"estYear": “1636”
}
let estDate = university.double(forKey: "estDate")
if estDate != 0.0 {
// Handle estDate
}else if let estYear = university.string(forKey: "estYear") {
// Handle estYear
}
A NoSQL Option for iOS :
A Sneak Peek
Couchbase Mobile Platform: Full Stack Database Platform
37
Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved.
Couchbase Lite Sync Gateway Couchbase Server
EMBEDDED DATABASE SYNCHRONIZATION DATABASE SERVER
SECURITY
NoSQL Document Style
Couchbase Lite
38
Mobile App
Couchbase Lite
Native API
Native Platform
Bindings
JSON
Lite Core Engine
Fleece
SQLite Engine
• Embedded NoSQL Database
• JSON Document Store
• Open Source
• iOS, Android, .NET…
• Encryption Support
• Powerful Query Interface, FTS
• Sync (full Couchbase stack)
• Conflict Resolver
Resources
39
• Couchbase Developer Portal
• https://developer.couchbase.com
• Source Code
• https://github.com/couchbaselabs
• https://github.com/couchbase/
• “Office Hours”
Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved.
Integrating into your iOS Project
40
developer.couchbase.com
Creating / Opening a Database
41
// Set Database configuration
var config = DatabaseConfiguration()
config.directory = userFolderPath
config.encryptionKey( /*encryption key object*/ )
config. conflictResolver(/*Set custom resolver */ )
// Create / Open a database with specified name and configuration
_db = try Database(name: kDBName, config: options)
Inserting Document
42
// Create a new document or update existing document
// If Id is not provided, system generates Id
let document = Document.init(id, dictionary: props)
try database.save(document)
Supported Data Types :
• Date
• Number
• Null
• String
• Array
• Blob
• Dictionary
Typed Accessors
Live Queries (w/ Full Text Search)
let query = Query.select(SelectResult.all())
.from(DataSource.database(database))
.where((Expression.property("skills").in(["music","writing"]))
.and(Expression.property("type").match(”student")))
.orderBy(Ordering.property("name").ascending()). toLive();
// Register for live query changes
_liveQueryListener = _bookingQuery?.addChangeListener({ [weak self](change) in
for (_, row) in (change.rows?.enumerated())! {
// handle row.document
default:
}})
query.run();
Thank you
@rajagp
44

More Related Content

PDF
Python business intelligence (PyData 2012 talk)
Stefan Urbanek
 
PPT
Ajax Lecture Notes
Santhiya Grace
 
PDF
Cubes – pluggable model explained
Stefan Urbanek
 
PDF
Cubes 1.0 Overview
Stefan Urbanek
 
PDF
Bubbles – Virtual Data Objects
Stefan Urbanek
 
PPTX
Using Spark to Load Oracle Data into Cassandra
Jim Hatcher
 
PPTX
EclipseCon 2021 NoSQL Endgame
Thodoris Bais
 
Python business intelligence (PyData 2012 talk)
Stefan Urbanek
 
Ajax Lecture Notes
Santhiya Grace
 
Cubes – pluggable model explained
Stefan Urbanek
 
Cubes 1.0 Overview
Stefan Urbanek
 
Bubbles – Virtual Data Objects
Stefan Urbanek
 
Using Spark to Load Oracle Data into Cassandra
Jim Hatcher
 
EclipseCon 2021 NoSQL Endgame
Thodoris Bais
 

What's hot (20)

KEY
Cubes - Lightweight Python OLAP (EuroPython 2012 talk)
Stefan Urbanek
 
PDF
Combine Spring Data Neo4j and Spring Boot to quickl
Neo4j
 
PDF
Data centric Metaprogramming by Vlad Ulreche
Spark Summit
 
PPTX
Reducing Development Time with MongoDB vs. SQL
MongoDB
 
PDF
Mongo db
Noman Ellahi
 
PPT
Spring data presentation
Oleksii Usyk
 
PPTX
Spring data jpa
Jeevesh Pandey
 
PDF
Data Binding in Silverlight
Boulos Dib
 
PPTX
Modeling JSON data for NoSQL document databases
Ryan CrawCour
 
PDF
Spark Dataframe - Mr. Jyotiska
Sigmoid
 
PPTX
U-SQL Killer Scenarios: Taming the Data Science Monster with U-SQL and Big Co...
Michael Rys
 
PDF
SDEC2011 NoSQL Data modelling
Korea Sdec
 
PPTX
Jdbc Java Programming
chhaichivon
 
PDF
GraphConnect Europe 2016 - Building Spring Data Neo4j 4.1 Applications Like A...
Neo4j
 
PDF
Rails database optimization
Karsten Meier
 
PPT
Hadoop World 2011: Building Web Analytics Processing on Hadoop at CBS Interac...
Cloudera, Inc.
 
PPTX
NoSQL Tel Aviv Meetup#1: NoSQL Data Modeling
NoSQL TLV
 
PPTX
OrientDB vs Neo4j - and an introduction to NoSQL databases
Curtis Mosters
 
PPTX
Spring framework part 2
Haroon Idrees
 
PPT
ADO.net control
Paneliya Prince
 
Cubes - Lightweight Python OLAP (EuroPython 2012 talk)
Stefan Urbanek
 
Combine Spring Data Neo4j and Spring Boot to quickl
Neo4j
 
Data centric Metaprogramming by Vlad Ulreche
Spark Summit
 
Reducing Development Time with MongoDB vs. SQL
MongoDB
 
Mongo db
Noman Ellahi
 
Spring data presentation
Oleksii Usyk
 
Spring data jpa
Jeevesh Pandey
 
Data Binding in Silverlight
Boulos Dib
 
Modeling JSON data for NoSQL document databases
Ryan CrawCour
 
Spark Dataframe - Mr. Jyotiska
Sigmoid
 
U-SQL Killer Scenarios: Taming the Data Science Monster with U-SQL and Big Co...
Michael Rys
 
SDEC2011 NoSQL Data modelling
Korea Sdec
 
Jdbc Java Programming
chhaichivon
 
GraphConnect Europe 2016 - Building Spring Data Neo4j 4.1 Applications Like A...
Neo4j
 
Rails database optimization
Karsten Meier
 
Hadoop World 2011: Building Web Analytics Processing on Hadoop at CBS Interac...
Cloudera, Inc.
 
NoSQL Tel Aviv Meetup#1: NoSQL Data Modeling
NoSQL TLV
 
OrientDB vs Neo4j - and an introduction to NoSQL databases
Curtis Mosters
 
Spring framework part 2
Haroon Idrees
 
ADO.net control
Paneliya Prince
 
Ad

Similar to Core Data Migrations and A Better Option (20)

PPT
Core Data Migration
Monica Kurup
 
PDF
Core data WIPJam workshop @ MWC'14
Diego Freniche Brito
 
PDF
Intro to Core Data
Make School
 
PDF
Core data in Swfit
allanh0526
 
PPT
Core data orlando i os dev group
Andrew Kozlik
 
PDF
CoreData Best Practices (2021)
deeje cooley
 
KEY
iOSDevCamp 2011 Core Data
Chris Mar
 
PDF
CoreData
Ali Akhtar
 
PDF
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
smn-automate
 
PDF
Core data intermediate Workshop at NSSpain 2013
Diego Freniche Brito
 
PDF
Advanced Core Data - The Things You Thought You Could Ignore
Aaron Douglas
 
PDF
Core Data with Swift 3.0
Korhan Bircan
 
ODP
MobileCity:Core Data
Allan Davis
 
PDF
Infinum iOS Talks S01E02 - Things every iOS developer should know about Core ...
Denis_infinum
 
PPTX
FluentMigrator - Dayton .NET - July 2023
Matthew Groves
 
PPTX
04 managing the database
Марина Босова
 
PDF
CoreData - there is an ORM you can like!
Tomáš Jukin
 
PDF
High Performance Core Data
Matthew Morey
 
PDF
Data Modeling and Relational to NoSQL
DATAVERSITY
 
PDF
Core data basic Workshop slides NSSpain 2013
Diego Freniche Brito
 
Core Data Migration
Monica Kurup
 
Core data WIPJam workshop @ MWC'14
Diego Freniche Brito
 
Intro to Core Data
Make School
 
Core data in Swfit
allanh0526
 
Core data orlando i os dev group
Andrew Kozlik
 
CoreData Best Practices (2021)
deeje cooley
 
iOSDevCamp 2011 Core Data
Chris Mar
 
CoreData
Ali Akhtar
 
CocoaHeads PDX 2014 01 23 : CoreData and iCloud Improvements iOS7 / OSX Maver...
smn-automate
 
Core data intermediate Workshop at NSSpain 2013
Diego Freniche Brito
 
Advanced Core Data - The Things You Thought You Could Ignore
Aaron Douglas
 
Core Data with Swift 3.0
Korhan Bircan
 
MobileCity:Core Data
Allan Davis
 
Infinum iOS Talks S01E02 - Things every iOS developer should know about Core ...
Denis_infinum
 
FluentMigrator - Dayton .NET - July 2023
Matthew Groves
 
04 managing the database
Марина Босова
 
CoreData - there is an ORM you can like!
Tomáš Jukin
 
High Performance Core Data
Matthew Morey
 
Data Modeling and Relational to NoSQL
DATAVERSITY
 
Core data basic Workshop slides NSSpain 2013
Diego Freniche Brito
 
Ad

Recently uploaded (20)

PDF
Oracle AI Vector Search- Getting Started and what's new in 2025- AIOUG Yatra ...
Sandesh Rao
 
PDF
BLW VOCATIONAL TRAINING SUMMER INTERNSHIP REPORT
codernjn73
 
PDF
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
PDF
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
PDF
Brief History of Internet - Early Days of Internet
sutharharshit158
 
PPTX
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
PDF
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
PDF
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
PDF
Advances in Ultra High Voltage (UHV) Transmission and Distribution Systems.pdf
Nabajyoti Banik
 
PPTX
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
PPTX
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
PDF
The Future of Mobile Is Context-Aware—Are You Ready?
iProgrammer Solutions Private Limited
 
PDF
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
PPTX
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
PDF
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
PDF
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
PDF
Using Anchore and DefectDojo to Stand Up Your DevSecOps Function
Anchore
 
PDF
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
PDF
Automating ArcGIS Content Discovery with FME: A Real World Use Case
Safe Software
 
PDF
AI-Cloud-Business-Management-Platforms-The-Key-to-Efficiency-Growth.pdf
Artjoker Software Development Company
 
Oracle AI Vector Search- Getting Started and what's new in 2025- AIOUG Yatra ...
Sandesh Rao
 
BLW VOCATIONAL TRAINING SUMMER INTERNSHIP REPORT
codernjn73
 
Security features in Dell, HP, and Lenovo PC systems: A research-based compar...
Principled Technologies
 
Google I/O Extended 2025 Baku - all ppts
HusseinMalikMammadli
 
Brief History of Internet - Early Days of Internet
sutharharshit158
 
IT Runs Better with ThousandEyes AI-driven Assurance
ThousandEyes
 
Make GenAI investments go further with the Dell AI Factory
Principled Technologies
 
Presentation about Hardware and Software in Computer
snehamodhawadiya
 
Advances in Ultra High Voltage (UHV) Transmission and Distribution Systems.pdf
Nabajyoti Banik
 
AI and Robotics for Human Well-being.pptx
JAYMIN SUTHAR
 
Applied-Statistics-Mastering-Data-Driven-Decisions.pptx
parmaryashparmaryash
 
The Future of Mobile Is Context-Aware—Are You Ready?
iProgrammer Solutions Private Limited
 
CIFDAQ's Market Wrap : Bears Back in Control?
CIFDAQ
 
New ThousandEyes Product Innovations: Cisco Live June 2025
ThousandEyes
 
Structs to JSON: How Go Powers REST APIs
Emily Achieng
 
AI Unleashed - Shaping the Future -Starting Today - AIOUG Yatra 2025 - For Co...
Sandesh Rao
 
Using Anchore and DefectDojo to Stand Up Your DevSecOps Function
Anchore
 
Tea4chat - another LLM Project by Kerem Atam
a0m0rajab1
 
Automating ArcGIS Content Discovery with FME: A Real World Use Case
Safe Software
 
AI-Cloud-Business-Management-Platforms-The-Key-to-Efficiency-Growth.pdf
Artjoker Software Development Company
 

Core Data Migrations and A Better Option

  • 1. Core Data Migrations and …can we do better? Priya Rajagopal @rajagp
  • 3. Core Data Stack 3 Managed Object Model (schema) Persistent Store Coordinator Managed Object Context (1 ..*) Managed Object Managed Object Managed Object Persistent Object Store (1..*) Persistent Store (1..*)
  • 4. Core Data Stack : iOS10 4 Persistent Container
  • 5. Managed Object Model 5 • Schema Definition • Entities , Attributes and Relationships • Versioning Image source: https://developer.apple.com/
  • 7. The Dreaded Persistent Store / Data Model Mismatch Exception! 7
  • 8. Option 1 : Delete the app and reinstall 8
  • 10. Option 2: Core Data Migrations 10 Managed Data Model (Source) Managed Data Model (Target) Source Data Store Mapping Model Target Data StoreMigration Policy
  • 11. Case 1 11 Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved. Source Model country domain name University Target Model country domain name University websiteweblink
  • 12. Lightweight Migrations 12 • Automatic Migrations • Core Data infers mapping model from source to target model • Fast • Handles following Changes • Simple addition /removal of a new attribute • A non-optional attribute becoming optional • An optional attribute becoming non-optional, and defining a default value • Renaming an entity or property • Simple Relationship changes • Simple entity hierarchy changes • Complete list https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/vmLightweightMigration.html#//apple_ref/doc/uid/TP40004399-CH4- SW2
  • 13. Configure Core Data Stack 13 let persistentStoreDesc = NSPersistentStoreDescription(url: storeUrl) persistentStoreDesc.shouldMigrateStoreAutomatically = true persistentStoreDesc.shouldInferMappingModelAutomatically = true self.persistentContainer?.persistentStoreDescriptions = [persistentStoreDesc]
  • 14. Some help from editor 14
  • 15. Case 2 15 Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved. Source Model country domain name University Target Model University website estDate (Date) country domain name website estYear (String)
  • 16. Custom Migration Policy 16 // Transform estDate of type Date to estYear of type String class UniversityDataMigrationPolicy: NSEntityMigrationPolicy { func transformEstDateToEstYear(_ estDate:NSDate)->String { let calendar = NSCalendar.current let components = calendar.dateComponents(Set<Calendar.Component>([.year]), from: estDate as Date) return "(components.year!)" } }
  • 19. Case 3 19 Source Model country domain name University Target Model University website estYear name domain name website estYear code country country *..1
  • 20. Custom Migration Policy (1/3) 20 class UniversityMigrationPolicy: NSEntityMigrationPolicy { override func createDestinationInstances(forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws { // 1. Create destination Instance corresponding to the source instance let dInstance = NSEntityDescription.insertNewObject(forEntityName: mapping.destinationEntityName!, into: manager.destinationContext) let sKeys = sInstance.entity.attributesByName.keys let sValues = sInstance.dictionaryWithValues(forKeys: Array(sKeys)) let dKeys = dInstance.entity.attributesByName.keys for dKey in dKeys { if let matchingValueInSrc = sValues[dKey] { dInstance.setValue(matchingValueInSrc, forKey: dKey) } }
  • 21. Custom Migration Policy (2/3) 21 let universityName = sValues["name"] if let countryName = sInstance.value(forKey: "country") as? String { // 2 . We are tracking the Country managed objects in Migration Manager’s userInfo // This is to ensure we create a single instance of Country for every countryName if let userInfo = manager.userInfo , let country = userInfo[countryName] as? NSManagedObject{ // link university entity to country dInstance.setValue(country, forKey: "country") } else {
  • 22. Custom Migration Policy (3/3) 22 // 3 . Create Country object let country = NSEntityDescription.insertNewObject(forEntityName: "Country", into: manager.destinationContext) // Set country name country.setValue(countryName, forKey: "name") // 4. Link University object with the corresponding Country object dInstance.setValue(country, forKey: "country") // 5. Track the newly created country object in Migration Manager’s userInfo if let _ = manager.userInfo { manager.userInfo?[countryName] = country } else { manager.userInfo = [:] manager.userInfo?[countryName] = country } } // 4. Associate the source with destination instance manager.associate(sourceInstance: sInstance, withDestinationInstance: dInstance, for: mapping) }
  • 24. Manual 24 let persistentStoreDesc = NSPersistentStoreDescription(url: storeUrl) persistentStoreDesc.shouldMigrateStoreAutomatically = false persistentStoreDesc.shouldInferMappingModelAutomatically = false self.persistentContainer?.persistentStoreDescriptions = [persistentStoreDesc] • Create Custom Migration Policies • Create Mapping Models
  • 25. 1. Test if Migration is Needed 25 func isMigrationNeeded()->Bool { …… let srcMetadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(ofType: NSSQLiteStoreType, at: sourceUrl, options: nil) let momPathValue = Bundle.main.path(forResource: "UniversityDataModel", ofType:"momd") guard let destModel = NSManagedObjectModel(contentsOf: URL(fileURLWithPath: momPathValue)) else { return false } return destModel.isConfiguration(withName: nil, compatibleWithStoreMetadata: srcMetadata) == false ? true: false …… }
  • 26. 2. Migrate Stores Progressively 26 func progressivelyMigrate() throws { // Get the model version that is compatible with the current data store let idx = try indexOfCompatibleMom(at: sourceUrl, moms: self.models) let remaining = self.models.suffix(from: (idx + 1)) guard remaining.count > 0 else { // The stored DB is compatible with the latest model return // migration not necessary } _ = try remaining.reduce(self.models[idx]) { smom, dmom in do { try self.migrate(srcStoreUrl: sourceUrl, srcModel: smom, dstModel: dmom) } catch { // handle error } return dmom } }
  • 27. 3. Identify Model compatible with Store 27 func indexOfCompatibleMom(at storeURL: URL, moms: [NSManagedObjectModel]) throws -> Int { let meta = try NSPersistentStoreCoordinator.metadataForPersistentStore(ofType: NSSQLiteStoreType, at: storeURL) guard let idx = moms.index(where: { $0.isConfiguration(withName: nil, compatibleWithStoreMetadata: meta) }) else { throw MigrationError.IncompatibleModels } return idx }
  • 28. 4. Migrate Store from src to dst model 28 func migrate(srcStoreUrl:URL, srcModel:NSManagedObjectModel,dstModel:NSManagedObjectModel)throws { // Prepare temp directory for destination let dir = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(UUID().uuidString) try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true, attributes: nil) defer { _ = try? FileManager.default.removeItem(at: dir) } // Perform migration let mapping = try findMapping(from: srcModel, to: dstModel) let destURL = dir.appendingPathComponent(srcStoreUrl.lastPathComponent) let manager = NSMigrationManager(sourceModel: srcModel, destinationModel: dstModel) try autoreleasepool { try manager.migrateStore( from: srcStoreUrl, sourceType: NSSQLiteStoreType, options: nil, with: mapping, toDestinationURL: destURL, destinationType: NSSQLiteStoreType, destinationOptions: nil ) }
  • 29. 5. Find Mapping Model 29 fileprivate func findMapping(from smom: NSManagedObjectModel, to dmom: NSManagedObjectModel) throws -> NSMappingModel { if let mapping = NSMappingModel(from: Bundle.allBundles, forSourceModel: smom, destinationModel: dmom) { return mapping // found custom mapping } // Return inferred mapping model if a custom model not defined. return try NSMappingModel.inferredMappingModel(forSourceModel: smom, destinationModel: dmom) }
  • 31. NoSQL Option for Persisting Data 31 • Non Relational • Unstructured or Semi Structured Data • Scalable – both up and down • SQL-type Queries Document • Couchbase • MongoDB • DynamoDB • DocumentDB Key-Value • Couchbase • Riak • BerkeleyDB • Redis • … Graph • OrientDB • Neo4J • DEX • GraphBase Wide Column • Hbase • Cassandra • Hypertable
  • 32. Data Modeling 32 Data Concern Core Data JSON Document Model (Couchbase) Rich Structure  Managed Object Model - entities  Documents = containers of related KV pairs Relationships  Represented  Represented (embed/reference) Structure Evolution  Migrations  Flexible  Dynamic change Value Evolution  Data can be updated  Data can be updated Query Interface  NSFetchRequest  NSFetchedResultsControllerDelegate  Query / LiveQuery
  • 33. JSON to Native Mapping 33
  • 34. NoSQL: Example 1 Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved. US Umich.edu University Of Michigan US harvard.edu Harvard University -10516645301 { "type":"university", "name":"University of Michigan", "domain":"umich.edu", "country":"US” } { "type":"university", "name":"Harvard University”, "domain":"harvard.edu", "country":"US", "estDate":-10516645301 }
  • 35. NoSQL : Example 2 Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved. US harvard.edu Harvard University { "type":"university", "name":"Harvard University", "domain":"harvard.edu”, "country":"US", "estDate":-10516645301 } -10516645301 (Double) US harvard.edu Harvard University “1636” (String) { "type":"university", "name":"Harvard University", "domain":"harvard.edu”, "country":"US", "estYear": “1636” } let estDate = university.double(forKey: "estDate") if estDate != 0.0 { // Handle estDate }else if let estYear = university.string(forKey: "estYear") { // Handle estYear }
  • 36. A NoSQL Option for iOS : A Sneak Peek
  • 37. Couchbase Mobile Platform: Full Stack Database Platform 37 Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved. Couchbase Lite Sync Gateway Couchbase Server EMBEDDED DATABASE SYNCHRONIZATION DATABASE SERVER SECURITY NoSQL Document Style
  • 38. Couchbase Lite 38 Mobile App Couchbase Lite Native API Native Platform Bindings JSON Lite Core Engine Fleece SQLite Engine • Embedded NoSQL Database • JSON Document Store • Open Source • iOS, Android, .NET… • Encryption Support • Powerful Query Interface, FTS • Sync (full Couchbase stack) • Conflict Resolver
  • 39. Resources 39 • Couchbase Developer Portal • https://developer.couchbase.com • Source Code • https://github.com/couchbaselabs • https://github.com/couchbase/ • “Office Hours” Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved.
  • 40. Integrating into your iOS Project 40 developer.couchbase.com
  • 41. Creating / Opening a Database 41 // Set Database configuration var config = DatabaseConfiguration() config.directory = userFolderPath config.encryptionKey( /*encryption key object*/ ) config. conflictResolver(/*Set custom resolver */ ) // Create / Open a database with specified name and configuration _db = try Database(name: kDBName, config: options)
  • 42. Inserting Document 42 // Create a new document or update existing document // If Id is not provided, system generates Id let document = Document.init(id, dictionary: props) try database.save(document) Supported Data Types : • Date • Number • Null • String • Array • Blob • Dictionary Typed Accessors
  • 43. Live Queries (w/ Full Text Search) let query = Query.select(SelectResult.all()) .from(DataSource.database(database)) .where((Expression.property("skills").in(["music","writing"])) .and(Expression.property("type").match(”student"))) .orderBy(Ordering.property("name").ascending()). toLive(); // Register for live query changes _liveQueryListener = _bookingQuery?.addChangeListener({ [weak self](change) in for (_, row) in (change.rows?.enumerated())! { // handle row.document default: }}) query.run();

Editor's Notes

  • #4: Framework for managing model layer. Persistence, Object graphs, persistence ,faults, querying. The entities in a store are created from a managed object model
  • #5: Core Data been around for for over a decade. Framework for managing model layer in MVP/MVVM/MVC apps. Persistence, Object graphs, persistence ,faults, querying
  • #6: Core Data Model Editor Persistent Store Coordinator loaded with instance of Managed Object Model Creates new managed objects from model Loads existing objects from persistent store
  • #7: Requirements constantly changing requiring changes to the data model No control over when users upgrade apps => Support multiple versions of data models The data model is inconsistent with the data in the store so cannot read the data in the store. Data in store corresponds to different model
  • #11: 1) Tries to find model to open source data store 2) Looks for mapping model to map from src to target or infers one 3) Applies migration policies to migrate object from src to dest store