[AltStoreCore] Flattens optional values when @Managed/@AsyncManaged.wrappedValue is also optional

This commit is contained in:
Riley Testut
2023-05-11 15:03:29 -05:00
committed by Magesh K
parent 7d380da5d1
commit 16c71be7f9
4 changed files with 46 additions and 2 deletions

View File

@@ -0,0 +1,19 @@
//
// OptionalProtocol.swift
// AltStoreCore
//
// Created by Riley Testut on 5/11/23.
// Copyright © 2023 Riley Testut. All rights reserved.
//
import Foundation
// Public so we can use as generic constraint.
public protocol OptionalProtocol
{
associatedtype Wrapped
static var none: Self { get }
}
extension Optional: OptionalProtocol {}

View File

@@ -71,6 +71,7 @@ public extension AsyncManaged
/// @dynamicMemberLookup
public extension AsyncManaged
{
// Non-optional values
subscript<T>(dynamicMember keyPath: KeyPath<ManagedObject, T>) -> T {
get async {
let result = await self.perform { $0[keyPath: keyPath] }
@@ -78,7 +79,7 @@ public extension AsyncManaged
}
}
// Optionals
// Optional wrapped value
subscript<Wrapped, T>(dynamicMember keyPath: KeyPath<Wrapped, T>) -> T? where ManagedObject == Optional<Wrapped> {
get async {
guard let wrappedValue else { return nil }
@@ -87,4 +88,14 @@ public extension AsyncManaged
return result
}
}
// Optional wrapped value + optional property (flattened)
subscript<Wrapped, T>(dynamicMember keyPath: KeyPath<Wrapped, T>) -> T where ManagedObject == Optional<Wrapped>, T: OptionalProtocol {
get async {
guard let wrappedValue else { return T.none }
let result = await self.perform { _ in wrappedValue[keyPath: keyPath] }
return result
}
}
}

View File

@@ -80,13 +80,14 @@ public extension Managed
/// @dynamicMemberLookup
public extension Managed
{
// Non-optional values
subscript<T>(dynamicMember keyPath: KeyPath<ManagedObject, T>) -> T
{
let result = self.perform { $0[keyPath: keyPath] }
return result
}
// Optionals
// Optional wrapped value
subscript<Wrapped, T>(dynamicMember keyPath: KeyPath<Wrapped, T>) -> T? where ManagedObject == Optional<Wrapped>
{
guard let wrappedValue else { return nil }
@@ -94,4 +95,13 @@ public extension Managed
let result = self.perform { _ in wrappedValue[keyPath: keyPath] }
return result
}
// Optional wrapped value + optional property (flattened)
subscript<Wrapped, T>(dynamicMember keyPath: KeyPath<Wrapped, T>) -> T where ManagedObject == Optional<Wrapped>, T: OptionalProtocol
{
guard let wrappedValue else { return T.none }
let result = self.perform { _ in wrappedValue[keyPath: keyPath] }
return result
}
}