[AltStoreCore] Adds @AsyncManaged property wrapper

Same as @Managed, except it supports using Swift Concurrency to fetch values from its managedObject’s managedObjectContext.
This commit is contained in:
Riley Testut
2023-04-04 14:11:58 -05:00
committed by Magesh K
parent fc99fb32a4
commit 12ca34f40f
2 changed files with 87 additions and 1 deletions

View File

@@ -0,0 +1,82 @@
//
// AsyncManaged.swift
// AltStore
//
// Created by Riley Testut on 3/30/23.
// Copyright © 2023 Riley Testut. All rights reserved.
//
import Foundation
import CoreData
@propertyWrapper @dynamicMemberLookup
public struct AsyncManaged<ManagedObject>
{
public var wrappedValue: ManagedObject {
didSet {
self.managedObjectContext = self.managedObject?.managedObjectContext
}
}
public var projectedValue: AsyncManaged<ManagedObject> {
return self
}
private var managedObjectContext: NSManagedObjectContext?
private var managedObject: NSManagedObject? {
return self.wrappedValue as? NSManagedObject
}
public init(wrappedValue: ManagedObject)
{
self.wrappedValue = wrappedValue
self.managedObjectContext = self.managedObject?.managedObjectContext
}
}
public extension AsyncManaged
{
// Fetch multiple values.
func get<T>(_ closure: @escaping (ManagedObject) -> T) async -> T
{
if let context = self.managedObjectContext
{
return await context.performAsync {
closure(self.wrappedValue)
}
}
else
{
return closure(self.wrappedValue)
}
}
}
/// @dynamicMemberLookup
extension AsyncManaged
{
public subscript<T>(dynamicMember keyPath: KeyPath<ManagedObject, T>) -> T {
get async {
guard let context = self.managedObjectContext else {
return self.wrappedValue[keyPath: keyPath]
}
return await context.performAsync {
return self.wrappedValue[keyPath: keyPath]
}
}
}
// Optionals
public subscript<Wrapped, T>(dynamicMember keyPath: KeyPath<Wrapped, T>) -> T? where ManagedObject == Optional<Wrapped> {
get async {
guard let context = self.managedObjectContext else {
return self.wrappedValue?[keyPath: keyPath]
}
return await context.performAsync {
return self.wrappedValue?[keyPath: keyPath]
}
}
}
}