diff --git a/Sources/SpeziAccount/Account.swift b/Sources/SpeziAccount/Account.swift index 3996f6df..0de4a206 100644 --- a/Sources/SpeziAccount/Account.swift +++ b/Sources/SpeziAccount/Account.swift @@ -9,30 +9,10 @@ import Spezi import SwiftUI -// TODO naming? +/// A property wrapper that can be used within ``AccountService`` instances to gain +/// access to the ``Account`` instance. typealias AccountReference = WeakInjectable -@propertyWrapper -public final class WeakInjectable { // TODO where to move? - private weak var weakReference: Type? - - public var wrappedValue: Type { - guard let weakReference else { - fatalError("Failed to retrieve `\(Type.self)` object from weak reference is not yet present or not present anymore.") - } - - return weakReference - } - - public init() {} - - func inject(_ type: Type) { - self.weakReference = type - } -} - -extension WeakInjectable: Sendable where Type: Sendable {} - /// Account-related Spezi module managing a collection of ``AccountService``s. /// TODO update docs! /// diff --git a/Sources/SpeziAccount/AccountDetails.swift b/Sources/SpeziAccount/AccountDetails.swift index 82e52b1b..4e31d028 100644 --- a/Sources/SpeziAccount/AccountDetails.swift +++ b/Sources/SpeziAccount/AccountDetails.swift @@ -24,6 +24,10 @@ public struct AccountDetails: Sendable, ModifiableAccountValueStorageContainer { internal let accountServiceId: ObjectIdentifier public var accountService: any AccountService { + guard _account.isInjected else { + fatalError("You can only access the `accountService` property of the `AccountDetails` if was supplied to the `Account` instance.") + } + guard let service = account.mappedAccountServices[accountServiceId] else { fatalError("AccountDetails stored an AccountService Id that wasn't present in the Account instance!") } diff --git a/Sources/SpeziAccount/Misc/WeakInjectable.swift b/Sources/SpeziAccount/Misc/WeakInjectable.swift new file mode 100644 index 00000000..c1339d46 --- /dev/null +++ b/Sources/SpeziAccount/Misc/WeakInjectable.swift @@ -0,0 +1,36 @@ +// +// This source file is part of the Spezi open-source project +// +// SPDX-FileCopyrightText: 2023 Stanford University and the project authors (see CONTRIBUTORS.md) +// +// SPDX-License-Identifier: MIT +// + +/// The property wrapper `WeakInjectable` can be used to transparently declare a weak property for a given class type. +@propertyWrapper +public final class WeakInjectable { + private weak var weakReference: Type? + + /// Queries if the reference was already injected. + public var isInjected: Bool { + weakReference != nil + } + + /// Access the underlying weak reference. + /// - Note: This will crash if the underlying value wasn't injected yet. + public var wrappedValue: Type { + guard let weakReference else { + fatalError("Failed to retrieve `\(Type.self)` object from weak reference is not yet present or not present anymore.") + } + + return weakReference + } + + public init() {} + + func inject(_ type: Type) { + self.weakReference = type + } +} + +extension WeakInjectable: Sendable where Type: Sendable {} \ No newline at end of file