diff --git a/MMMLoadable.podspec b/MMMLoadable.podspec index 725ddf7..e50fdd9 100644 --- a/MMMLoadable.podspec +++ b/MMMLoadable.podspec @@ -6,7 +6,7 @@ Pod::Spec.new do |s| s.name = "MMMLoadable" - s.version = "2.0.0" + s.version = "2.1.0" s.summary = "A simple model for async calculations" s.description = "#{s.summary}." s.homepage = "https://github.com/mediamonks/#{s.name}" diff --git a/Sources/MMMLoadable/MMMLoadable.swift b/Sources/MMMLoadable/MMMLoadable.swift index 350f7d9..0a6389e 100644 --- a/Sources/MMMLoadable/MMMLoadable.swift +++ b/Sources/MMMLoadable/MMMLoadable.swift @@ -31,6 +31,34 @@ extension MMMPureLoadableProtocol { block(self) } } + + /// Waits for the receiver to stop syncing and continues if `isContentsAvailable`; throws otherwise. + public func doneSyncing() async throws { + try await contentsAfterDoneSyncing { _ in } + } + + /// Waits for the receiver to stop syncing; then, if `isContentsAvailable`, returns the result of the given closure; + /// throws otherwise. + public func contentsAfterDoneSyncing(_ grabContents: @escaping (Self) throws -> T) async throws -> T { + try await withCheckedThrowingContinuation { continuation in + DispatchQueue.main.async { + var waiter: MMMSimpleLoadableWaiter? + waiter = MMMSimpleLoadableWaiter.whenDoneSyncing(self) { + do { + if self.isContentsAvailable { + continuation.resume(returning: try grabContents(self)) + } else { + throw self.error ?? NSError(domain: self, message: "Unspecified error") + } + } catch { + continuation.resume(throwing: error) + } + // We need to keep the waiter around while waiting. + _ = waiter + } + } + } + } } /// Forwards all calls in `MMMPureLoadableProtocol` to another object.