mastodon-app-ufficiale-ipho.../MastodonSDK/Sources/CoreDataStack/Extension/NSManagedObjectContext.swift

113 lines
3.4 KiB
Swift

//
// NSManagedObjectContext.swift
// CoreDataStack
//
// Created by Cirno MainasuK on 2020-8-10.
//
import os
import Foundation
import Combine
import CoreData
extension NSManagedObjectContext {
public func insert<T: NSManagedObject>() -> T where T: Managed {
guard let object = NSEntityDescription.insertNewObject(forEntityName: T.entityName, into: self) as? T else {
fatalError("cannot insert object: \(T.self)")
}
return object
}
public func saveOrRollback() throws {
do {
guard hasChanges else {
return
}
try save()
} catch {
rollback()
os_log("%{public}s[%{public}ld], %{public}s: %s", ((#file as NSString).lastPathComponent), #line, #function, error.localizedDescription)
throw error
}
}
public func performChanges(block: @escaping () -> Void) -> Future<Result<Void, Error>, Never> {
Future { promise in
self.perform {
block()
do {
try self.saveOrRollback()
promise(.success(Result.success(())))
} catch {
promise(.success(Result.failure(error)))
}
}
}
}
}
extension NSManagedObjectContext {
public func perform<T>(block: @escaping () throws -> T) async throws -> T {
if #available(iOS 15.0, *) {
return try await perform(schedule: .enqueued) {
try block()
}
} else {
return try await withCheckedThrowingContinuation { continuation in
self.perform {
do {
let value = try block()
continuation.resume(returning: value)
} catch {
continuation.resume(throwing: error)
}
}
} // end return
}
}
public func performChanges<T>(block: @escaping () throws -> T) async throws -> T {
if #available(iOS 15.0, *) {
return try await perform(schedule: .enqueued) {
let value = try block()
try self.saveOrRollback()
return value
}
} else {
return try await withCheckedThrowingContinuation { continuation in
self.perform {
do {
let value = try block()
try self.saveOrRollback()
continuation.resume(returning: value)
} catch {
continuation.resume(throwing: error)
}
}
} // end return
}
} // end func
}
extension NSManagedObjectContext {
static let objectCacheKey = "ObjectCacheKey"
private typealias ObjectCache = [String: NSManagedObject]
public func cache(
_ object: NSManagedObject?,
key: String
) {
var cache = userInfo[NSManagedObjectContext.objectCacheKey] as? ObjectCache ?? [:]
cache[key] = object
userInfo[NSManagedObjectContext.objectCacheKey] = cache
}
public func cache(froKey key: String) -> NSManagedObject? {
guard let cache = userInfo[NSManagedObjectContext.objectCacheKey] as? ObjectCache
else { return nil }
return cache[key]
}
}