mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-01-16 05:56:50 +01:00
async API prototypes
This commit is contained in:
@@ -46,7 +46,11 @@ public final class DataStack: Equatable {
|
||||
- parameter bundle: an optional bundle to load .xcdatamodeld models from. If not specified, the main bundle will be used.
|
||||
- parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
public convenience init(xcodeModelName: XcodeDataModelFileName = DataStack.applicationName, bundle: Bundle = Bundle.main, migrationChain: MigrationChain = nil) {
|
||||
public convenience init(
|
||||
xcodeModelName: XcodeDataModelFileName = DataStack.applicationName,
|
||||
bundle: Bundle = Bundle.main,
|
||||
migrationChain: MigrationChain = nil
|
||||
) {
|
||||
|
||||
self.init(
|
||||
schemaHistory: SchemaHistory(
|
||||
@@ -79,7 +83,11 @@ public final class DataStack: Equatable {
|
||||
- parameter otherSchema: a list of other `DynamicSchema` instances that represent present/previous/future model versions, in any order
|
||||
- parameter migrationChain: the `MigrationChain` that indicates the sequence of model versions to be used as the order for progressive migrations. If not specified, will default to a non-migrating data stack.
|
||||
*/
|
||||
public convenience init(_ schema: DynamicSchema, _ otherSchema: DynamicSchema..., migrationChain: MigrationChain = nil) {
|
||||
public convenience init(
|
||||
_ schema: DynamicSchema,
|
||||
_ otherSchema: DynamicSchema...,
|
||||
migrationChain: MigrationChain = nil
|
||||
) {
|
||||
|
||||
self.init(
|
||||
schemaHistory: SchemaHistory(
|
||||
@@ -108,7 +116,9 @@ public final class DataStack: Equatable {
|
||||
```
|
||||
- parameter schemaHistory: the `SchemaHistory` for the stack
|
||||
*/
|
||||
public required init(schemaHistory: SchemaHistory) {
|
||||
public required init(
|
||||
schemaHistory: SchemaHistory
|
||||
) {
|
||||
|
||||
self.coordinator = NSPersistentStoreCoordinator(managedObjectModel: schemaHistory.rawModel)
|
||||
self.rootSavingContext = NSManagedObjectContext.rootSavingContextForCoordinator(self.coordinator)
|
||||
@@ -139,7 +149,9 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `DataStack`'s model.
|
||||
*/
|
||||
public func entityTypesByName(for type: NSManagedObject.Type) -> [EntityName: NSManagedObject.Type] {
|
||||
public func entityTypesByName(
|
||||
for type: NSManagedObject.Type
|
||||
) -> [EntityName: NSManagedObject.Type] {
|
||||
|
||||
var entityTypesByName: [EntityName: NSManagedObject.Type] = [:]
|
||||
for (entityIdentifier, entityDescription) in self.schemaHistory.entityDescriptionsByEntityIdentifier {
|
||||
@@ -163,7 +175,9 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the entity name-to-class type mapping from the `DataStack`'s model.
|
||||
*/
|
||||
public func entityTypesByName(for type: CoreStoreObject.Type) -> [EntityName: CoreStoreObject.Type] {
|
||||
public func entityTypesByName(
|
||||
for type: CoreStoreObject.Type
|
||||
) -> [EntityName: CoreStoreObject.Type] {
|
||||
|
||||
var entityTypesByName: [EntityName: CoreStoreObject.Type] = [:]
|
||||
for (entityIdentifier, entityDescription) in self.schemaHistory.entityDescriptionsByEntityIdentifier {
|
||||
@@ -191,7 +205,9 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the `NSEntityDescription` for the specified `NSManagedObject` subclass.
|
||||
*/
|
||||
public func entityDescription(for type: NSManagedObject.Type) -> NSEntityDescription? {
|
||||
public func entityDescription(
|
||||
for type: NSManagedObject.Type
|
||||
) -> NSEntityDescription? {
|
||||
|
||||
return self.entityDescription(for: Internals.EntityIdentifier(type))
|
||||
}
|
||||
@@ -199,7 +215,9 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the `NSEntityDescription` for the specified `CoreStoreObject` subclass.
|
||||
*/
|
||||
public func entityDescription(for type: CoreStoreObject.Type) -> NSEntityDescription? {
|
||||
public func entityDescription(
|
||||
for type: CoreStoreObject.Type
|
||||
) -> NSEntityDescription? {
|
||||
|
||||
return self.entityDescription(for: Internals.EntityIdentifier(type))
|
||||
}
|
||||
@@ -207,7 +225,9 @@ public final class DataStack: Equatable {
|
||||
/**
|
||||
Returns the `NSManagedObjectID` for the specified object URI if it exists in the persistent store.
|
||||
*/
|
||||
public func objectID(forURIRepresentation url: URL) -> NSManagedObjectID? {
|
||||
public func objectID(
|
||||
forURIRepresentation url: URL
|
||||
) -> NSManagedObjectID? {
|
||||
|
||||
return self.coordinator.managedObjectID(forURIRepresentation: url)
|
||||
}
|
||||
@@ -236,7 +256,9 @@ public final class DataStack: Equatable {
|
||||
- returns: the `StorageInterface` added to the stack
|
||||
*/
|
||||
@discardableResult
|
||||
public func addStorageAndWait<T: StorageInterface>(_ storage: T) throws -> T {
|
||||
public func addStorageAndWait<T: StorageInterface>(
|
||||
_ storage: T
|
||||
) throws -> T {
|
||||
|
||||
do {
|
||||
|
||||
@@ -275,7 +297,9 @@ public final class DataStack: Equatable {
|
||||
- returns: the local storage added to the stack. Note that this may not always be the same instance as the parameter argument if a previous `LocalStorage` was already added at the same URL and with the same configuration.
|
||||
*/
|
||||
@discardableResult
|
||||
public func addStorageAndWait<T: LocalStorage>(_ storage: T) throws -> T {
|
||||
public func addStorageAndWait<T: LocalStorage>(
|
||||
_ storage: T
|
||||
) throws -> T {
|
||||
|
||||
return try self.coordinator.performSynchronously {
|
||||
|
||||
@@ -374,7 +398,9 @@ public final class DataStack: Equatable {
|
||||
Prepares deinitializing the `DataStack` by removing all persistent stores. This is not necessary, but can help silence SQLite warnings when actively releasing and recreating `DataStack`s.
|
||||
- parameter completion: the closure to execute after all persistent stores are removed
|
||||
*/
|
||||
public func unsafeRemoveAllPersistentStores(completion: @escaping () -> Void = {}) {
|
||||
public func unsafeRemoveAllPersistentStores(
|
||||
completion: @escaping () -> Void = {}
|
||||
) {
|
||||
|
||||
let coordinator = self.coordinator
|
||||
coordinator.performAsynchronously {
|
||||
@@ -441,7 +467,7 @@ public final class DataStack: Equatable {
|
||||
internal let mainContext: NSManagedObjectContext
|
||||
internal let schemaHistory: SchemaHistory
|
||||
internal let childTransactionQueue = DispatchQueue.serial("com.coreStore.dataStack.childTransactionQueue", qos: .utility)
|
||||
internal let storeMetadataUpdateQueue = DispatchQueue.concurrent("com.coreStore.persistentStoreBarrierQueue", qos: .userInteractive)
|
||||
internal let storeMetadataLock: NSRecursiveLock = .init()
|
||||
internal let migrationQueue: OperationQueue = Internals.with {
|
||||
|
||||
let migrationQueue = OperationQueue()
|
||||
@@ -452,56 +478,68 @@ public final class DataStack: Equatable {
|
||||
return migrationQueue
|
||||
}
|
||||
|
||||
internal func persistentStoreForStorage(_ storage: StorageInterface) -> NSPersistentStore? {
|
||||
internal func persistentStoreForStorage(
|
||||
_ storage: StorageInterface
|
||||
) -> NSPersistentStore? {
|
||||
|
||||
return self.coordinator.persistentStores
|
||||
.filter { $0.storageInterface === storage }
|
||||
.first
|
||||
}
|
||||
|
||||
internal func persistentStores(for entityIdentifier: Internals.EntityIdentifier) -> [NSPersistentStore]? {
|
||||
|
||||
var returnValue: [NSPersistentStore]? = nil
|
||||
self.storeMetadataUpdateQueue.sync(flags: .barrier) {
|
||||
|
||||
returnValue = self.finalConfigurationsByEntityIdentifier[entityIdentifier]?
|
||||
.map({ self.persistentStoresByFinalConfiguration[$0]! }) ?? []
|
||||
internal func persistentStores(
|
||||
for entityIdentifier: Internals.EntityIdentifier
|
||||
) -> [NSPersistentStore]? {
|
||||
|
||||
self.storeMetadataLock.lock()
|
||||
defer {
|
||||
self.storeMetadataLock.unlock()
|
||||
}
|
||||
return returnValue
|
||||
return self.finalConfigurationsByEntityIdentifier[entityIdentifier]?
|
||||
.map({ self.persistentStoresByFinalConfiguration[$0]! }) ?? []
|
||||
}
|
||||
|
||||
internal func persistentStore(for entityIdentifier: Internals.EntityIdentifier, configuration: ModelConfiguration, inferStoreIfPossible: Bool) -> (store: NSPersistentStore?, isAmbiguous: Bool) {
|
||||
|
||||
return self.storeMetadataUpdateQueue.sync(flags: .barrier) { () -> (store: NSPersistentStore?, isAmbiguous: Bool) in
|
||||
|
||||
let configurationsForEntity = self.finalConfigurationsByEntityIdentifier[entityIdentifier] ?? []
|
||||
if let configuration = configuration {
|
||||
|
||||
if configurationsForEntity.contains(configuration) {
|
||||
|
||||
return (store: self.persistentStoresByFinalConfiguration[configuration], isAmbiguous: false)
|
||||
}
|
||||
else if !inferStoreIfPossible {
|
||||
|
||||
return (store: nil, isAmbiguous: false)
|
||||
}
|
||||
internal func persistentStore(
|
||||
for entityIdentifier: Internals.EntityIdentifier,
|
||||
configuration: ModelConfiguration,
|
||||
inferStoreIfPossible: Bool
|
||||
) -> (store: NSPersistentStore?, isAmbiguous: Bool) {
|
||||
|
||||
self.storeMetadataLock.lock()
|
||||
defer {
|
||||
self.storeMetadataLock.unlock()
|
||||
}
|
||||
let configurationsForEntity = self.finalConfigurationsByEntityIdentifier[entityIdentifier] ?? []
|
||||
if let configuration = configuration {
|
||||
|
||||
if configurationsForEntity.contains(configuration) {
|
||||
|
||||
return (store: self.persistentStoresByFinalConfiguration[configuration], isAmbiguous: false)
|
||||
}
|
||||
|
||||
switch configurationsForEntity.count {
|
||||
|
||||
case 0:
|
||||
else if !inferStoreIfPossible {
|
||||
|
||||
return (store: nil, isAmbiguous: false)
|
||||
|
||||
case 1 where inferStoreIfPossible:
|
||||
return (store: self.persistentStoresByFinalConfiguration[configurationsForEntity.first!], isAmbiguous: false)
|
||||
|
||||
default:
|
||||
return (store: nil, isAmbiguous: true)
|
||||
}
|
||||
}
|
||||
|
||||
switch configurationsForEntity.count {
|
||||
|
||||
case 0:
|
||||
return (store: nil, isAmbiguous: false)
|
||||
|
||||
case 1 where inferStoreIfPossible:
|
||||
return (store: self.persistentStoresByFinalConfiguration[configurationsForEntity.first!], isAmbiguous: false)
|
||||
|
||||
default:
|
||||
return (store: nil, isAmbiguous: true)
|
||||
}
|
||||
}
|
||||
|
||||
internal func createPersistentStoreFromStorage(_ storage: StorageInterface, finalURL: URL?, finalStoreOptions: [AnyHashable: Any]?) throws -> NSPersistentStore {
|
||||
internal func createPersistentStoreFromStorage(
|
||||
_ storage: StorageInterface,
|
||||
finalURL: URL?,
|
||||
finalStoreOptions: [AnyHashable: Any]?
|
||||
) throws -> NSPersistentStore {
|
||||
|
||||
let persistentStore = try self.coordinator.addPersistentStore(
|
||||
ofType: type(of: storage).storeType,
|
||||
@@ -510,8 +548,13 @@ public final class DataStack: Equatable {
|
||||
options: finalStoreOptions
|
||||
)
|
||||
persistentStore.storageInterface = storage
|
||||
|
||||
self.storeMetadataUpdateQueue.async(flags: .barrier) {
|
||||
|
||||
do {
|
||||
|
||||
self.storeMetadataLock.lock()
|
||||
defer {
|
||||
self.storeMetadataLock.unlock()
|
||||
}
|
||||
|
||||
let configurationName = persistentStore.configurationName
|
||||
self.persistentStoresByFinalConfiguration[configurationName] = persistentStore
|
||||
@@ -534,7 +577,9 @@ public final class DataStack: Equatable {
|
||||
return persistentStore
|
||||
}
|
||||
|
||||
internal func entityDescription(for entityIdentifier: Internals.EntityIdentifier) -> NSEntityDescription? {
|
||||
internal func entityDescription(
|
||||
for entityIdentifier: Internals.EntityIdentifier
|
||||
) -> NSEntityDescription? {
|
||||
|
||||
return self.schemaHistory.entityDescriptionsByEntityIdentifier[entityIdentifier]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user