mirror of
https://github.com/JohnEstropia/CoreStore.git
synced 2026-09-10 20:02:02 +02:00
Initial prototype for Swift 6 mode
This commit is contained in:
@@ -24,7 +24,8 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreData
|
||||
@preconcurrency import CoreData
|
||||
import os
|
||||
|
||||
|
||||
// MARK: - DataStack
|
||||
@@ -49,7 +50,7 @@ extension DataStack {
|
||||
*/
|
||||
public func addStorage<T>(
|
||||
_ storage: T,
|
||||
completion: @escaping (SetupResult<T>) -> Void
|
||||
completion: @escaping @MainActor (SetupResult<T>) -> Void
|
||||
) {
|
||||
|
||||
self.coordinator.performAsynchronously {
|
||||
@@ -110,7 +111,7 @@ extension DataStack {
|
||||
*/
|
||||
public func addStorage<T: LocalStorage>(
|
||||
_ storage: T,
|
||||
completion: @escaping (SetupResult<T>) -> Void
|
||||
completion: @escaping @MainActor (SetupResult<T>) -> Void
|
||||
) -> Progress? {
|
||||
|
||||
let fileURL = storage.fileURL
|
||||
@@ -162,7 +163,7 @@ extension DataStack {
|
||||
attributes: nil
|
||||
)
|
||||
|
||||
let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
|
||||
nonisolated(unsafe) let metadata = try NSPersistentStoreCoordinator.metadataForPersistentStore(
|
||||
ofType: type(of: storage).storeType,
|
||||
at: fileURL as URL,
|
||||
options: storage.storeOptions
|
||||
@@ -192,12 +193,18 @@ extension DataStack {
|
||||
}
|
||||
catch {
|
||||
|
||||
completion(.failure(CoreStoreError(error)))
|
||||
DispatchQueue.main.async {
|
||||
|
||||
completion(.failure(CoreStoreError(error)))
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
completion(.failure(CoreStoreError(error)))
|
||||
DispatchQueue.main.async {
|
||||
|
||||
completion(.failure(CoreStoreError(error)))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -212,7 +219,10 @@ extension DataStack {
|
||||
}
|
||||
catch {
|
||||
|
||||
completion(.failure(CoreStoreError(error)))
|
||||
DispatchQueue.main.async {
|
||||
|
||||
completion(.failure(CoreStoreError(error)))
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -264,7 +274,7 @@ extension DataStack {
|
||||
*/
|
||||
public func upgradeStorageIfNeeded<T: LocalStorage>(
|
||||
_ storage: T,
|
||||
completion: @escaping (MigrationResult) -> Void
|
||||
completion: @escaping @MainActor (MigrationResult) -> Void
|
||||
) throws(CoreStoreError) -> Progress? {
|
||||
|
||||
return try self.coordinator.performSynchronously {
|
||||
@@ -376,7 +386,7 @@ extension DataStack {
|
||||
private func upgradeStorageIfNeeded<T: LocalStorage>(
|
||||
_ storage: T,
|
||||
metadata: [String: Any],
|
||||
completion: @escaping (MigrationResult) -> Void
|
||||
completion: @escaping @MainActor (MigrationResult) -> Void
|
||||
) -> Progress? {
|
||||
|
||||
guard let migrationSteps = self.computeMigrationFromStorage(storage, metadata: metadata) else {
|
||||
@@ -423,9 +433,13 @@ extension DataStack {
|
||||
}
|
||||
|
||||
let migrationTypes = migrationSteps.map { $0.migrationType }
|
||||
var migrationResult: MigrationResult?
|
||||
let migrationState: OSAllocatedUnfairLock<(migrationResult: MigrationResult?, cancelled: Bool)> = .init(
|
||||
initialState: (
|
||||
migrationResult: nil,
|
||||
cancelled: false
|
||||
)
|
||||
)
|
||||
var operations = [Operation]()
|
||||
var cancelled = false
|
||||
|
||||
let progress = Progress(parent: nil, userInfo: nil)
|
||||
progress.totalUnitCount = numberOfMigrations
|
||||
@@ -440,12 +454,15 @@ extension DataStack {
|
||||
operations.append(
|
||||
BlockOperation { [weak self] in
|
||||
|
||||
guard let self = self, !cancelled else {
|
||||
guard
|
||||
let self = self,
|
||||
!migrationState.withLock({ $0.cancelled })
|
||||
else {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
autoreleasepool {
|
||||
Internals.autoreleasepool {
|
||||
|
||||
do {
|
||||
|
||||
@@ -465,8 +482,14 @@ extension DataStack {
|
||||
migrationError,
|
||||
"Failed to migrate version model \"\(migrationType.sourceVersion)\" to version \"\(migrationType.destinationVersion)\"."
|
||||
)
|
||||
migrationResult = .failure(migrationError)
|
||||
cancelled = true
|
||||
migrationState.withLock { state in
|
||||
|
||||
if !state.cancelled {
|
||||
|
||||
state.migrationResult = .failure(migrationError)
|
||||
state.cancelled = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -488,7 +511,10 @@ extension DataStack {
|
||||
DispatchQueue.main.async {
|
||||
|
||||
progress.setProgressHandler(nil)
|
||||
completion(migrationResult ?? .success(migrationTypes))
|
||||
completion(
|
||||
migrationState.withLock { $0.migrationResult }
|
||||
?? .success(migrationTypes)
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -594,22 +620,28 @@ extension DataStack {
|
||||
let estimatedTime: TimeInterval = 60 * 3 // 3 mins
|
||||
let interval: TimeInterval = 1
|
||||
let fakeTotalUnitCount: Float = 0.9 * Float(progress.totalUnitCount)
|
||||
var fakeProgress: Float = 0
|
||||
let fakeProgress: OSAllocatedUnfairLock<Float> = .init(initialState: 0)
|
||||
|
||||
var recursiveCheck: () -> Void = {}
|
||||
recursiveCheck = { [weak timerQueue] in
|
||||
@Sendable
|
||||
func recursiveCheck() {
|
||||
|
||||
guard let timerQueue = timerQueue, fakeProgress < 1 else {
|
||||
let enqueueNext = fakeProgress.withLock {
|
||||
|
||||
return
|
||||
guard $0 < 1.0 else {
|
||||
|
||||
return false
|
||||
}
|
||||
progress.completedUnitCount = Int64(fakeTotalUnitCount * $0)
|
||||
$0 += Float(interval / estimatedTime)
|
||||
return true
|
||||
}
|
||||
if enqueueNext {
|
||||
|
||||
timerQueue.asyncAfter(
|
||||
deadline: .now() + interval,
|
||||
execute: recursiveCheck
|
||||
)
|
||||
}
|
||||
progress.completedUnitCount = Int64(fakeTotalUnitCount * fakeProgress)
|
||||
fakeProgress += Float(interval / estimatedTime)
|
||||
|
||||
timerQueue.asyncAfter(
|
||||
deadline: .now() + interval,
|
||||
execute: recursiveCheck
|
||||
)
|
||||
}
|
||||
timerQueue.async(execute: recursiveCheck)
|
||||
|
||||
@@ -626,7 +658,7 @@ extension DataStack {
|
||||
}
|
||||
timerQueue.sync {
|
||||
|
||||
fakeProgress = 1
|
||||
fakeProgress.withLock({ $0 = 1.0 })
|
||||
}
|
||||
_ = try? storage.cs_finalizeStorageAndWait(soureModelHint: destinationModel)
|
||||
progress.completedUnitCount = progress.totalUnitCount
|
||||
|
||||
Reference in New Issue
Block a user