Skip to content
This repository has been archived by the owner on Nov 29, 2023. It is now read-only.

Commit

Permalink
Some more XPC helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
mattmassicotte committed Aug 5, 2022
1 parent 20a5fed commit ea44fa0
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 0 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ Task.ordered {

### CancellingContinuation

Going to deprecate this one. Check out `withContinuation` below.

Just like a `CheckedContinuation`, but will automatically resume by throwing if it is deallocated without being resumed manually. This is useful for situations where you cannot guarantee that a closure will be called. An example of such a situation is an XPC call.

```swift
Expand All @@ -60,6 +62,14 @@ try await withCancellingContinuation({ continuation in
})
```

### NSXPCConnection Extensions

You might be tempted to make your XPC interface functions `async`. While this does work, it does not correctly handle connection failures and is unsafe. This little `NSXPCConnection` extension provides a safe way to get into the async world. This is preferred over using `CancellingContinuation`.

```swift
func withContinuation<Service, T>(function: String = #function, _ body: (Service, CheckedContinuation<T, Error>) -> Void) async throws -> T
```

### Suggestions or Feedback

We'd love to hear from you! Get in touch via [twitter](https://twitter.com/chimehq), an issue, or a pull request.
Expand Down
1 change: 1 addition & 0 deletions Sources/ConcurrencyPlus/CancellingContinuation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Foundation

public enum CancellingContinuationError: Error {
case cancelledOnDeinit
case missingBothValueAndError
}

/// A continuation that will automatically throw if deallocated without being resumed
Expand Down
41 changes: 41 additions & 0 deletions Sources/ConcurrencyPlus/Continuation+Resuming.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,44 @@ extension CancellingContinuation where T == Void {
}
}
}

extension CancellingContinuation {
public func resume(with value: T?, error: Error?) {
switch (value, error) {
case (let value?, nil):
resume(returning: value)
case (_, let error?):
resume(throwing: error)
case (nil, nil):
resume(throwing: CancellingContinuationError.missingBothValueAndError)
}
}
}

extension CheckedContinuation where E == Error {
public func resume(with value: T?, error: Error?) {
switch (value, error) {
case (let value?, nil):
resume(returning: value)
case (_, let error?):
resume(throwing: error)
case (nil, nil):
resume(throwing: ConnectionContinuationError.missingBothValueAndError)
}
}

public var resumingHandler: (T?, Error?) -> Void {
return {
self.resume(with: $0, error: $1)
}
}
}

extension CheckedContinuation where T == Void, E == Error {
public var resumingHandler: (Error?) -> Void {
return {
resume(with: $0)
}
}
}

24 changes: 24 additions & 0 deletions Sources/ConcurrencyPlus/NSXPCConnection+Continuation.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Foundation

public enum ConnectionContinuationError: Error {
case serviceTypeMismatch
case missingBothValueAndError
}

public extension NSXPCConnection {
/// Create a continuation that is automatically cancelled on connection failure
func withContinuation<Service, T>(function: String = #function, _ body: (Service, CheckedContinuation<T, Error>) -> Void) async throws -> T {
return try await withCheckedThrowingContinuation(function: function) { continuation in
let proxy = self.remoteObjectProxyWithErrorHandler { error in
continuation.resume(throwing: error)
}

guard let service = proxy as? Service else {
continuation.resume(throwing: ConnectionContinuationError.serviceTypeMismatch)
return
}

body(service, continuation)
}
}
}

0 comments on commit ea44fa0

Please sign in to comment.