From 7d380da5d19250c6bc8ef47447b15a88046a17fb Mon Sep 17 00:00:00 2001 From: Riley Testut Date: Thu, 11 May 2023 14:45:09 -0500 Subject: [PATCH] [AltStoreCore] Adds Managed.perform() to match AsyncManaged --- AltStoreCore/Types/Managed.swift | 68 ++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/AltStoreCore/Types/Managed.swift b/AltStoreCore/Types/Managed.swift index fe91c3d4..d591e5ae 100644 --- a/AltStoreCore/Types/Managed.swift +++ b/AltStoreCore/Types/Managed.swift @@ -10,18 +10,15 @@ import Foundation import CoreData @propertyWrapper @dynamicMemberLookup -struct Managed -struct Managed +public struct Managed { public var wrappedValue: ManagedObject { didSet { self.managedObjectContext = self.managedObject?.managedObjectContext - self.managedObjectContext = self.managedObject?.managedObjectContext } } - - var projectedValue: Managed { + public var projectedValue: Managed { return self } @@ -29,43 +26,72 @@ struct Managed private var managedObject: NSManagedObject? { return self.wrappedValue as? NSManagedObject } - - init(wrappedValue: ManagedObject) + + public init(wrappedValue: ManagedObject) { self.wrappedValue = wrappedValue self.managedObjectContext = self.managedObject?.managedObjectContext - self.managedObjectContext = self.managedObject?.managedObjectContext } - - public subscript(dynamicMember keyPath: KeyPath) -> T +} + +/// Run on managedObjectContext's queue. +public extension Managed +{ + // Non-throwing + func perform(_ closure: @escaping (ManagedObject) -> T) -> T { var result: T! if let context = self.managedObjectContext { context.performAndWait { - result = self.wrappedValue[keyPath: keyPath] + result = closure(self.wrappedValue) } } else { - result = self.wrappedValue[keyPath: keyPath] + result = closure(self.wrappedValue) } return result } - - // Optionals - subscript(dynamicMember keyPath: KeyPath) -> T? where ManagedObject == Optional { - var result: T? - - if let context = self.managedObjectContext { + + // Throwing + func perform(_ closure: @escaping (ManagedObject) throws -> T) throws -> T + { + var result: Result! + + if let context = self.managedObjectContext + { context.performAndWait { - result = self.wrappedValue?[keyPath: keyPath] as? T + result = Result { try closure(self.wrappedValue) } } - } else { - result = self.wrappedValue?[keyPath: keyPath] as? T } + else + { + result = Result { try closure(self.wrappedValue) } + } + + let value = try result.get() + return value + } +} + +/// @dynamicMemberLookup +public extension Managed +{ + subscript(dynamicMember keyPath: KeyPath) -> T + { + let result = self.perform { $0[keyPath: keyPath] } + return result + } + + // Optionals + subscript(dynamicMember keyPath: KeyPath) -> T? where ManagedObject == Optional + { + guard let wrappedValue else { return nil } + + let result = self.perform { _ in wrappedValue[keyPath: keyPath] } return result } }