WIP: custom migration

This commit is contained in:
John Rommel Estropia
2017-05-09 03:10:35 +09:00
parent 6d04806608
commit 9d65a27557
37 changed files with 1642 additions and 588 deletions
+2 -2
View File
@@ -125,7 +125,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
return bridge(error) {
try self.bridgeToSwift.addStorageAndWait(InMemoryStore.self)
try self.bridgeToSwift.addStorageAndWait(InMemoryStore())
}
}
@@ -143,7 +143,7 @@ public final class CSDataStack: NSObject, CoreStoreObjectiveCType {
return bridge(error) {
try self.bridgeToSwift.addStorageAndWait(SQLiteStore.self)
try self.bridgeToSwift.addStorageAndWait(SQLiteStore())
}
}
+51
View File
@@ -0,0 +1,51 @@
//
// CSDynamicSchema.swift
// CoreStore
//
// Copyright © 2017 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import CoreData
import Foundation
// MARK: - CSDynamicSchema
/**
The `CSDynamicSchema` serves as the Objective-C bridging type for `DynamicSchema`.
- SeeAlso: `DynamicSchema`
*/
@objc
public protocol CSDynamicSchema {
/**
The version string for this model schema.
*/
@objc
var modelVersion: ModelVersion { get }
/**
Do not call this directly. The `NSManagedObjectModel` for this schema may be created lazily and using this method directly may affect the integrity of the model.
*/
@objc
func rawModel() -> NSManagedObjectModel
}
@@ -0,0 +1,109 @@
//
// CSLegacyXcodeDataModelSchema.swift
// CoreStore
//
// Copyright © 2017 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import CoreData
import Foundation
// MARK: - CSLegacyXcodeDataModelSchema
/**
The `CSLegacyXcodeDataModelSchema` serves as the Objective-C bridging type for `LegacyXcodeDataModelSchema`.
- SeeAlso: `LegacyXcodeDataModelSchema`
*/
@objc
public final class CSLegacyXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
@objc
public required init(modelName: ModelVersion, model: NSManagedObjectModel) {
self.bridgeToSwift = LegacyXcodeDataModelSchema(
modelName: modelName,
model: model
)
}
// MARK: NSObject
public override var hash: Int {
return ObjectIdentifier(self.bridgeToSwift).hashValue
}
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSLegacyXcodeDataModelSchema else {
return false
}
return self.bridgeToSwift === object.bridgeToSwift
}
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
// MARK: CSDynamicSchema
@objc
public var modelVersion: ModelVersion {
return self.bridgeToSwift.modelVersion
}
@objc
public func rawModel() -> NSManagedObjectModel {
return self.bridgeToSwift.rawModel()
}
// MARK: CoreStoreObjectiveCType
public let bridgeToSwift: LegacyXcodeDataModelSchema
public required init(_ swiftValue: LegacyXcodeDataModelSchema) {
self.bridgeToSwift = swiftValue
super.init()
}
}
// MARK: - LegacyXcodeDataModelSchema
extension LegacyXcodeDataModelSchema: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSLegacyXcodeDataModelSchema {
return CSLegacyXcodeDataModelSchema(self)
}
}
+59 -13
View File
@@ -40,19 +40,18 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
/**
Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
- parameter fileURL: the local file URL for the target SQLite persistent store. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`.
*/
@objc
public convenience init(fileURL: URL, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
public convenience init(fileURL: URL, configuration: ModelConfiguration, localStorageOptions: Int) {
self.init(
SQLiteStore(
fileURL: fileURL,
configuration: configuration,
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
)
)
@@ -61,29 +60,27 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
/**
Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
- Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`.
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS). Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`.
*/
@objc
public convenience init(fileName: String, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
public convenience init(fileName: String, configuration: ModelConfiguration, localStorageOptions: Int) {
self.init(
SQLiteStore(
fileName: fileName,
configuration: configuration,
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
)
)
}
/**
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `.AllowProgresiveMigration`.
Initializes an `CSSQLiteStore` with an all-default settings: a `fileURL` pointing to a "<Application name>.sqlite" file in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS), a `nil` `configuration` pertaining to the "Default" configuration, a `mappingModelBundles` set to search all `NSBundle`s, and `localStorageOptions` set to `[CSLocalStorageOptions none]`.
- Warning: The default SQLite file location for the `CSLegacySQLiteStore` and `CSSQLiteStore` are different. If the app was depending on CoreStore's default directories prior to 2.0.0, make sure to use `CSLegacySQLiteStore` instead of `CSSQLiteStore`.
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
*/
@objc
public convenience override init() {
@@ -104,12 +101,12 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
}
/**
The `NSBundle`s from which to search mapping models for migrations
An array of `SchemaMappingProvider`s that provides the complete mapping models for custom migrations. This is currently only supported for Swift code.
*/
@objc
public var mappingModelBundles: [Bundle] {
return self.bridgeToSwift.mappingModelBundles
public var migrationMappingProviders: [Any] {
return self.bridgeToSwift.migrationMappingProviders
}
/**
@@ -194,6 +191,55 @@ public final class CSSQLiteStore: NSObject, CSLocalStorage, CoreStoreObjectiveCT
self.bridgeToSwift = swiftValue
super.init()
}
// MARK: Deprecated
/**
Initializes an SQLite store interface from the given SQLite file URL. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
- parameter fileURL: the local file URL for the target SQLite persistent store. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileURL` explicitly for each of them.
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration.
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `CSLocalStorageOptionsNone`.
*/
@available(*, deprecated: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileURL:configuration:localStorageOptions:]) initializer instead.")
@objc
public convenience init(fileURL: URL, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
self.init(
SQLiteStore(
fileURL: fileURL,
configuration: configuration,
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
)
)
}
/**
Initializes an SQLite store interface from the given SQLite file name. When this instance is passed to the `CSDataStack`'s `-addStorage*:` methods, a new SQLite file will be created if it does not exist.
- Important: Initializing `CSSQLiteStore`s with custom migration mapping models is currently not supported. Create an `SQLiteStore` instance from Swift code and bridge the instance to Objective-C using its `SQLiteStore.bridgeToObjectiveC` property.
- parameter fileName: the local filename for the SQLite persistent store in the "Application Support/<bundle id>" directory (or the "Caches/<bundle id>" directory on tvOS). Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter configuration: an optional configuration name from the model file. If not specified, defaults to `nil`, the "Default" configuration. Note that if you have multiple configurations, you will need to specify a different `fileName` explicitly for each of them.
- parameter mappingModelBundles: a list of `NSBundle`s from which to search mapping models for migration
- parameter localStorageOptions: When the `CSSQLiteStore` is passed to the `CSDataStack`'s `addStorage()` methods, tells the `CSDataStack` how to setup the persistent store. Defaults to `[CSLocalStorageOptions none]`.
*/
@available(*, deprecated: 3.1, message: "The `mappingModelBundles` argument of this method is ignored. Use the new -[CSSQLiteStore initWithFileName:configuration:localStorageOptions:]) initializer instead.")
@objc
public convenience init(fileName: String, configuration: ModelConfiguration, mappingModelBundles: [Bundle]?, localStorageOptions: Int) {
self.init(
SQLiteStore(
fileName: fileName,
configuration: configuration,
mappingModelBundles: mappingModelBundles ?? Bundle.allBundles,
localStorageOptions: LocalStorageOptions(rawValue: localStorageOptions)
)
)
}
}
+2 -2
View File
@@ -106,10 +106,10 @@ public protocol CSLocalStorage: CSStorageInterface {
var fileURL: URL { get }
/**
The `NSBundle`s from which to search mapping models for migrations
An array of `SchemaMappingProvider`s that provides the complete mapping models for custom migrations. This is currently only supported for Swift code.
*/
@objc
var mappingModelBundles: [Bundle] { get }
var migrationMappingProviders: [Any] { get }
/**
Options that tell the `CSDataStack` how to setup the persistent store
@@ -0,0 +1,109 @@
//
// CSXcodeDataModelSchema.swift
// CoreStore
//
// Copyright © 2017 John Rommel Estropia
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
import CoreData
import Foundation
// MARK: - CSXcodeDataModelSchema
/**
The `CSXcodeDataModelSchema` serves as the Objective-C bridging type for `XcodeDataModelSchema`.
- SeeAlso: `XcodeDataModelSchema`
*/
@objc
public final class CSXcodeDataModelSchema: NSObject, CSDynamicSchema, CoreStoreObjectiveCType {
@objc
public required init(modelVersion: ModelVersion, modelVersionFileURL: URL) {
self.bridgeToSwift = XcodeDataModelSchema(
modelVersion: modelVersion,
modelVersionFileURL: modelVersionFileURL
)
}
// MARK: NSObject
public override var hash: Int {
return ObjectIdentifier(self.bridgeToSwift).hashValue
}
public override func isEqual(_ object: Any?) -> Bool {
guard let object = object as? CSXcodeDataModelSchema else {
return false
}
return self.bridgeToSwift === object.bridgeToSwift
}
public override var description: String {
return "(\(String(reflecting: type(of: self)))) \(self.bridgeToSwift.coreStoreDumpString)"
}
// MARK: CSDynamicSchema
@objc
public var modelVersion: ModelVersion {
return self.bridgeToSwift.modelVersion
}
@objc
public func rawModel() -> NSManagedObjectModel {
return self.bridgeToSwift.rawModel()
}
// MARK: CoreStoreObjectiveCType
public let bridgeToSwift: XcodeDataModelSchema
public required init(_ swiftValue: XcodeDataModelSchema) {
self.bridgeToSwift = swiftValue
super.init()
}
}
// MARK: - XcodeDataModelSchema
extension XcodeDataModelSchema: CoreStoreSwiftType {
// MARK: CoreStoreSwiftType
public var bridgeToObjectiveC: CSXcodeDataModelSchema {
return CSXcodeDataModelSchema(self)
}
}
+5
View File
@@ -76,6 +76,11 @@ internal func bridge<T: CoreStoreSwiftType>(_ closure: () -> T) -> T.ObjectiveCT
return closure().bridgeToObjectiveC
}
internal func bridge<T: CoreStoreSwiftType>(_ closure: () -> [T]) -> [T.ObjectiveCType] {
return closure().map { $0.bridgeToObjectiveC }
}
internal func bridge<T: CoreStoreSwiftType>(_ closure: () -> T?) -> T.ObjectiveCType? {
return closure()?.bridgeToObjectiveC