Skip to content

Commit

Permalink
Fail safe
Browse files Browse the repository at this point in the history
  • Loading branch information
Supereg committed Jul 10, 2023
1 parent b910fd8 commit d0e30a8
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 22 deletions.
24 changes: 2 additions & 22 deletions Sources/SpeziAccount/Account.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<Account>

@propertyWrapper
public final class WeakInjectable<Type: AnyObject> { // 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!
///
Expand Down
4 changes: 4 additions & 0 deletions Sources/SpeziAccount/AccountDetails.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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!")
}
Expand Down
36 changes: 36 additions & 0 deletions Sources/SpeziAccount/Misc/WeakInjectable.swift
Original file line number Diff line number Diff line change
@@ -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<Type: AnyObject> {
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 {}

0 comments on commit d0e30a8

Please sign in to comment.