diff --git a/AltStoreCore/Types/Managed.swift b/AltStoreCore/Types/Managed.swift index a7a11f48..d591e5ae 100644 --- a/AltStoreCore/Types/Managed.swift +++ b/AltStoreCore/Types/Managed.swift @@ -32,41 +32,66 @@ public struct Managed self.wrappedValue = wrappedValue 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 - public subscript(dynamicMember keyPath: KeyPath) -> T? where ManagedObject == Optional + // Throwing + func perform(_ closure: @escaping (ManagedObject) throws -> T) throws -> T { - var result: 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 + 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 } }