Skip to content

Commit 773ff10

Browse files
committed
Removed fluff
1 parent 24f9777 commit 773ff10

8 files changed

Lines changed: 105 additions & 122 deletions

File tree

CoreDataMigration-Example.xcodeproj/project.pbxproj

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
434FE74B2F795ACA00359208 /* CoreDataManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434FE7402F795ACA00359208 /* CoreDataManagerTests.swift */; };
3939
434FE74C2F795ACA00359208 /* CoreDataMigratorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434FE7422F795ACA00359208 /* CoreDataMigratorTests.swift */; };
4040
434FE74D2F795ADC00359208 /* TestingAppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434FE7372F795ACA00359208 /* TestingAppDelegate.swift */; };
41-
434FE7502F795AFD00359208 /* CoreDataMigratorMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434FE74E2F795AFD00359208 /* CoreDataMigratorMock.swift */; };
41+
434FE7502F795AFD00359208 /* StubCoreDataMigrator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434FE74E2F795AFD00359208 /* StubCoreDataMigrator.swift */; };
4242
434FE7532F795B5400359208 /* StubCoreDataMigrationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 434FE7512F795B5400359208 /* StubCoreDataMigrationModel.swift */; };
4343
43EC64232F79925F0055607E /* CoreDataVersionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43EC64222F79925E0055607E /* CoreDataVersionTests.swift */; };
4444
/* End PBXBuildFile section */
@@ -89,7 +89,7 @@
8989
434FE7402F795ACA00359208 /* CoreDataManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManagerTests.swift; sourceTree = "<group>"; };
9090
434FE7412F795ACA00359208 /* CoreDataMigrationModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataMigrationModelTests.swift; sourceTree = "<group>"; };
9191
434FE7422F795ACA00359208 /* CoreDataMigratorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataMigratorTests.swift; sourceTree = "<group>"; };
92-
434FE74E2F795AFD00359208 /* CoreDataMigratorMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataMigratorMock.swift; sourceTree = "<group>"; };
92+
434FE74E2F795AFD00359208 /* StubCoreDataMigrator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubCoreDataMigrator.swift; sourceTree = "<group>"; };
9393
434FE7512F795B5400359208 /* StubCoreDataMigrationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StubCoreDataMigrationModel.swift; sourceTree = "<group>"; };
9494
43AB8AE51F66E6A5003153B3 /* CoreDataMigration-Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "CoreDataMigration-Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
9595
43AB8AFC1F66E6A5003153B3 /* CoreDataMigration-ExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "CoreDataMigration-ExampleTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -257,7 +257,7 @@
257257
isa = PBXGroup;
258258
children = (
259259
434FE7372F795ACA00359208 /* TestingAppDelegate.swift */,
260-
434FE74E2F795AFD00359208 /* CoreDataMigratorMock.swift */,
260+
434FE74E2F795AFD00359208 /* StubCoreDataMigrator.swift */,
261261
434FE7512F795B5400359208 /* StubCoreDataMigrationModel.swift */,
262262
);
263263
path = Doubles;
@@ -474,7 +474,7 @@
474474
buildActionMask = 2147483647;
475475
files = (
476476
434FE7492F795ACA00359208 /* CoreDataMigrationModelTests.swift in Sources */,
477-
434FE7502F795AFD00359208 /* CoreDataMigratorMock.swift in Sources */,
477+
434FE7502F795AFD00359208 /* StubCoreDataMigrator.swift in Sources */,
478478
434FE74A2F795ACA00359208 /* TestingAppDelegate.swift in Sources */,
479479
434FE74B2F795ACA00359208 /* CoreDataManagerTests.swift in Sources */,
480480
434FE7532F795B5400359208 /* StubCoreDataMigrationModel.swift in Sources */,

CoreDataMigration-Example/CoreData/CoreDataManager.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import CoreData
1111

1212
class CoreDataManager {
1313

14-
let migrator: CoreDataMigrator
14+
let migrator: CoreDataMigrating
1515

16-
lazy var persistentContainer: NSPersistentContainer! = {
16+
lazy var persistentContainer: NSPersistentContainer = {
1717
let persistentContainer = NSPersistentContainer(name: "CoreDataMigration_Example")
1818
let description = persistentContainer.persistentStoreDescriptions.first
1919
description?.shouldInferMappingModelAutomatically = false //inferred mapping will be handled else where
@@ -41,23 +41,21 @@ class CoreDataManager {
4141

4242
// MARK: - Init
4343

44-
init(migrator: CoreDataMigrator = CoreDataMigrator()) {
44+
init(migrator: CoreDataMigrating = CoreDataMigrator()) {
4545
self.migrator = migrator
4646
}
4747

4848
// MARK: - SetUp
4949

5050
func setup(completion: @escaping () -> Void) {
51-
loadPersistentStore {
52-
completion()
53-
}
51+
loadPersistentStore(completion: completion)
5452
}
5553

5654
// MARK: - Loading
5755

5856
private func loadPersistentStore(completion: @escaping () -> Void) {
5957
migrateStoreIfNeeded {
60-
self.persistentContainer.loadPersistentStores { description, error in
58+
self.persistentContainer.loadPersistentStores { _, error in
6159
guard error == nil else {
6260
fatalError("Unable to load store \(error!)")
6361
}

CoreDataMigration-Example/CoreData/Migration/CoreDataMigrationModel.swift

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,10 @@ import Foundation
1010
import CoreData
1111

1212
class CoreDataMigrationModel {
13-
let version: CoreDataVersion
14-
15-
var modelBundle: Bundle {
16-
return Bundle.main
17-
}
18-
19-
var modelDirectoryName: String {
20-
return "CoreDataMigration_Example.momd"
21-
}
13+
private let version: CoreDataVersion
2214

2315
static var all: [CoreDataMigrationModel] {
24-
var migrationModels = [CoreDataMigrationModel]()
25-
26-
for version in CoreDataVersion.allCases {
27-
migrationModels.append(CoreDataMigrationModel(version: version))
28-
}
29-
30-
return migrationModels
16+
return CoreDataVersion.allCases.map { CoreDataMigrationModel(version: $0) }
3117
}
3218

3319
static var current: CoreDataMigrationModel {
@@ -56,8 +42,13 @@ class CoreDataMigrationModel {
5642
// MARK: - Model
5743

5844
func managedObjectModel() -> NSManagedObjectModel {
59-
let omoURL = modelBundle.url(forResource: version.rawValue, withExtension: "omo", subdirectory: modelDirectoryName) // optimized model file
60-
let momURL = modelBundle.url(forResource: version.rawValue, withExtension: "mom", subdirectory: modelDirectoryName)
45+
let omoURL = Bundle.main.url(forResource: version.rawValue,
46+
withExtension: "omo",
47+
subdirectory: "CoreDataMigration_Example.momd") // optimized model file
48+
49+
let momURL = Bundle.main.url(forResource: version.rawValue,
50+
withExtension: "mom",
51+
subdirectory: "CoreDataMigration_Example.momd")
6152

6253
guard let url = omoURL ?? momURL else {
6354
fatalError("Unable to find model in bundle")
@@ -83,18 +74,19 @@ class CoreDataMigrationModel {
8374
func customMappingModel(to nextVersion: CoreDataMigrationModel) -> NSMappingModel? {
8475
let sourceModel = managedObjectModel()
8576
let destinationModel = nextVersion.managedObjectModel()
86-
guard let mapping = NSMappingModel(from: [modelBundle], forSourceModel: sourceModel, destinationModel: destinationModel) else {
87-
return nil
88-
}
89-
90-
return mapping
77+
78+
return NSMappingModel(from: [Bundle.main],
79+
forSourceModel: sourceModel,
80+
destinationModel: destinationModel)
9181
}
9282

9383
func inferredMappingModel(to nextVersion: CoreDataMigrationModel) -> NSMappingModel {
9484
do {
9585
let sourceModel = managedObjectModel()
9686
let destinationModel = nextVersion.managedObjectModel()
97-
return try NSMappingModel.inferredMappingModel(forSourceModel: sourceModel, destinationModel: destinationModel)
87+
88+
return try NSMappingModel.inferredMappingModel(forSourceModel: sourceModel,
89+
destinationModel: destinationModel)
9890
} catch {
9991
fatalError("Unable to generate inferred mapping model")
10092
}
@@ -114,7 +106,9 @@ class CoreDataMigrationModel {
114106
let sourceModel = managedObjectModel()
115107
let destinationModel = nextVersion.managedObjectModel()
116108

117-
let step = CoreDataMigrationStep(source: sourceModel, destination: destinationModel, mapping: mapping)
109+
let step = CoreDataMigrationStep(source: sourceModel,
110+
destination: destinationModel,
111+
mapping: mapping)
118112
let nextStep = nextVersion.migrationSteps(to: version)
119113

120114
return [step] + nextStep
@@ -124,7 +118,8 @@ class CoreDataMigrationModel {
124118

125119
static func migrationModelCompatibleWithStoreMetadata(_ metadata: [String : Any]) -> CoreDataMigrationModel? {
126120
let compatibleMigrationModel = CoreDataMigrationModel.all.first {
127-
$0.managedObjectModel().isConfiguration(withName: nil, compatibleWithStoreMetadata: metadata)
121+
$0.managedObjectModel().isConfiguration(withName: nil,
122+
compatibleWithStoreMetadata: metadata)
128123
}
129124

130125
return compatibleMigrationModel

CoreDataMigration-Example/CoreData/Migration/CoreDataMigrator.swift

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88

99
import CoreData
1010

11+
protocol CoreDataMigrating {
12+
func requiresMigration(at storeURL: URL) -> Bool
13+
func migrateStore(at storeURL: URL)
14+
}
15+
1116
/**
1217
Responsible for handling Core Data model migrations.
1318

@@ -24,16 +29,17 @@ import CoreData
2429
Then when we create model version 5, we only need to create one additional mapping 4 to 5. This greatly reduces the work
2530
required when adding a new version.
2631
*/
27-
class CoreDataMigrator {
32+
class CoreDataMigrator: CoreDataMigrating {
2833

2934
// MARK: - Check
3035

31-
func requiresMigration(at storeURL: URL, currentMigrationModel: CoreDataMigrationModel = CoreDataMigrationModel.current) -> Bool {
36+
func requiresMigration(at storeURL: URL) -> Bool {
3237
guard let metadata = NSPersistentStoreCoordinator.metadata(at: storeURL) else {
3338
return false
3439
}
3540

36-
return !currentMigrationModel.managedObjectModel().isConfiguration(withName: nil, compatibleWithStoreMetadata: metadata)
41+
return !CoreDataMigrationModel.current.managedObjectModel().isConfiguration(withName: nil,
42+
compatibleWithStoreMetadata: metadata)
3743
}
3844

3945
// MARK: - Migration
@@ -42,7 +48,9 @@ class CoreDataMigrator {
4248
migrateStore(from: storeURL, to: storeURL, targetVersion: CoreDataMigrationModel.current)
4349
}
4450

45-
func migrateStore(from sourceURL: URL, to targetURL: URL, targetVersion: CoreDataMigrationModel) {
51+
private func migrateStore(from sourceURL: URL,
52+
to targetURL: URL,
53+
targetVersion: CoreDataMigrationModel) {
4654
guard let metadata = NSPersistentStoreCoordinator.metadata(at: sourceURL),
4755
let sourceMigrationModel = CoreDataMigrationModel.migrationModelCompatibleWithStoreMetadata(metadata) else {
4856
fatalError("Unknown store version at URL \(sourceURL)")
@@ -54,11 +62,20 @@ class CoreDataMigrator {
5462
let migrationSteps = sourceMigrationModel.migrationSteps(to: targetVersion)
5563

5664
for step in migrationSteps {
57-
let manager = NSMigrationManager(sourceModel: step.source, destinationModel: step.destination)
58-
let destinationURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true).appendingPathComponent(UUID().uuidString)
65+
let manager = NSMigrationManager(sourceModel: step.source,
66+
destinationModel: step.destination)
67+
let tmpDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(),
68+
isDirectory: true)
69+
let destinationURL = tmpDirectoryURL.appendingPathComponent(UUID().uuidString)
5970

6071
do {
61-
try manager.migrateStore(from: currentURL, sourceType: NSSQLiteStoreType, options: nil, with: step.mapping, toDestinationURL: destinationURL, destinationType: NSSQLiteStoreType, destinationOptions: nil)
72+
try manager.migrateStore(from: currentURL,
73+
sourceType: NSSQLiteStoreType,
74+
options: nil,
75+
with: step.mapping,
76+
toDestinationURL: destinationURL,
77+
destinationType: NSSQLiteStoreType,
78+
destinationOptions: nil)
6279
} catch let error {
6380
fatalError("Failed attempting to migrate from \(step.source) to \(step.destination), error: \(error)")
6481
}
@@ -71,7 +88,8 @@ class CoreDataMigrator {
7188
currentURL = destinationURL
7289
}
7390

74-
NSPersistentStoreCoordinator.replaceStore(at: targetURL, withStoreAt: currentURL)
91+
NSPersistentStoreCoordinator.replaceStore(at: targetURL,
92+
withStoreAt: currentURL)
7593

7694
if (currentURL != sourceURL) {
7795
NSPersistentStoreCoordinator.destroyStore(at: currentURL)
@@ -80,8 +98,9 @@ class CoreDataMigrator {
8098

8199
// MARK: - WAL
82100

83-
func forceWALCheckpointingForStore(at storeURL: URL) {
84-
guard let metadata = NSPersistentStoreCoordinator.metadata(at: storeURL), let migrationModel = CoreDataMigrationModel.migrationModelCompatibleWithStoreMetadata(metadata) else {
101+
private func forceWALCheckpointingForStore(at storeURL: URL) {
102+
guard let metadata = NSPersistentStoreCoordinator.metadata(at: storeURL),
103+
let migrationModel = CoreDataMigrationModel.migrationModelCompatibleWithStoreMetadata(metadata) else {
85104
return
86105
}
87106

@@ -90,7 +109,8 @@ class CoreDataMigrator {
90109
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
91110

92111
let options = [NSSQLitePragmasOption: ["journal_mode": "DELETE"]]
93-
let store = persistentStoreCoordinator.addPersistentStore(at: storeURL, options: options)
112+
let store = persistentStoreCoordinator.addPersistentStore(at: storeURL,
113+
options: options)
94114
try persistentStoreCoordinator.remove(store)
95115
} catch let error {
96116
fatalError("Failed to force WAL checkpointing, error: \(error)")

CoreDataMigration-ExampleTests/Doubles/CoreDataMigratorMock.swift renamed to CoreDataMigration-ExampleTests/Doubles/StubCoreDataMigrator.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,23 +11,23 @@ import CoreData
1111

1212
@testable import CoreDataMigration_Example
1313

14-
class CoreDataMigratorMock: CoreDataMigrator {
14+
class StubCoreDataMigrator: CoreDataMigrating {
1515
enum Event {
16-
case requiresMigration(URL, CoreDataMigrationModel)
16+
case requiresMigration(URL)
1717
case migrateStore(URL)
1818
}
1919

2020
private(set) var events: [Event] = []
2121

2222
var requiresMigrationToBeReturned: Bool!
2323

24-
override func requiresMigration(at: URL, currentMigrationModel: CoreDataMigrationModel = CoreDataMigrationModel.current) -> Bool {
25-
events.append(.requiresMigration(at, currentMigrationModel))
24+
func requiresMigration(at storeURL: URL) -> Bool {
25+
events.append(.requiresMigration(storeURL))
2626

2727
return requiresMigrationToBeReturned
2828
}
2929

30-
override func migrateStore(at: URL) {
31-
events.append(.migrateStore(at))
30+
func migrateStore(at storeURL: URL) {
31+
events.append(.migrateStore(storeURL))
3232
}
3333
}

CoreDataMigration-ExampleTests/Tests/CoreDataManagerTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ import CoreData
1212
@testable import CoreDataMigration_Example
1313

1414
class CoreDataManagerTests: XCTestCase {
15-
var migrator: CoreDataMigratorMock!
15+
var migrator: StubCoreDataMigrator!
1616
var sut: CoreDataManager!
1717

1818
// MARK: - Setup
1919

2020
override func setUp() {
2121
super.setUp()
2222

23-
migrator = CoreDataMigratorMock()
23+
migrator = StubCoreDataMigrator()
2424
sut = CoreDataManager(migrator: migrator)
2525
}
2626

@@ -43,7 +43,7 @@ class CoreDataManagerTests: XCTestCase {
4343
expectation.fulfill()
4444
}
4545

46-
waitForExpectations(timeout: 10)
46+
waitForExpectations(timeout: 5)
4747
}
4848

4949
func test_givenNoMigrationRequired_whenSetup_thenChecksIfMigrationRequiredButDoesNotMigrate() {
@@ -66,7 +66,7 @@ class CoreDataManagerTests: XCTestCase {
6666
expectation.fulfill()
6767
}
6868

69-
waitForExpectations(timeout: 10)
69+
waitForExpectations(timeout: 5)
7070
}
7171

7272
func test_givenMigrationRequired_whenSetup_thenMigratesStore() {
@@ -84,6 +84,6 @@ class CoreDataManagerTests: XCTestCase {
8484
expectation.fulfill()
8585
}
8686

87-
waitForExpectations(timeout: 10)
87+
waitForExpectations(timeout: 5)
8888
}
8989
}

CoreDataMigration-ExampleTests/Tests/CoreDataMigrationModelTests.swift

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ class CoreDataMigrationModelTests: XCTestCase {
1919

2020
func test_givenLatestVersion_whenAccessingCurrent_thenReturnsLatestVersion() {
2121
let currentModel = CoreDataMigrationModel.current
22+
let expectedModel = CoreDataMigrationModel(version: .version4)
2223

23-
XCTAssertEqual(currentModel.version, CoreDataVersion.latest)
24+
XCTAssertEqual(currentModel.managedObjectModel(), expectedModel.managedObjectModel())
2425
}
2526

2627
// MARK: - All
@@ -33,29 +34,32 @@ class CoreDataMigrationModelTests: XCTestCase {
3334

3435
func test_givenAllVersionsExist_whenAccessingAll_thenModelsAreInVersionOrder() {
3536
let allModels = CoreDataMigrationModel.all
36-
let allVersions = allModels.map { $0.version }
37+
let expectedModels = CoreDataVersion.allCases.map { CoreDataMigrationModel(version: $0).managedObjectModel() }
3738

38-
XCTAssertEqual(allVersions, CoreDataVersion.allCases)
39+
XCTAssertEqual(allModels.map { $0.managedObjectModel() }, expectedModels)
3940
}
4041

4142
// MARK: - Successor
4243

4344
func test_givenVersion1_whenAccessingSuccessor_thenReturnsVersion2() {
4445
let sut = CoreDataMigrationModel(version: .version1)
46+
let expected = CoreDataMigrationModel(version: .version2)
4547

46-
XCTAssertEqual(sut.successor?.version, .version2)
48+
XCTAssertEqual(sut.successor?.managedObjectModel(), expected.managedObjectModel())
4749
}
4850

4951
func test_givenVersion2_whenAccessingSuccessor_thenReturnsVersion3() {
5052
let sut = CoreDataMigrationModel(version: .version2)
53+
let expected = CoreDataMigrationModel(version: .version3)
5154

52-
XCTAssertEqual(sut.successor?.version, .version3)
55+
XCTAssertEqual(sut.successor?.managedObjectModel(), expected.managedObjectModel())
5356
}
5457

5558
func test_givenVersion3_whenAccessingSuccessor_thenReturnsVersion4() {
5659
let sut = CoreDataMigrationModel(version: .version3)
60+
let expected = CoreDataMigrationModel(version: .version4)
5761

58-
XCTAssertEqual(sut.successor?.version, .version4)
62+
XCTAssertEqual(sut.successor?.managedObjectModel(), expected.managedObjectModel())
5963
}
6064

6165
func test_givenVersion4_whenAccessingSuccessor_thenReturnsNil() {

0 commit comments

Comments
 (0)