Skip to content

Instantly share code, notes, and snippets.

@brianmichel
Created June 5, 2021 12:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brianmichel/4b6e335222d1ee52e027f65d96447a3d to your computer and use it in GitHub Desktop.
Save brianmichel/4b6e335222d1ee52e027f65d96447a3d to your computer and use it in GitHub Desktop.
Publisher-ify NSExtensionContext item loading
import Combine
import Foundation
extension NSExtensionContext {
enum Errors: Error {
/// An error passed when there is no error, and no item is returned.
case unableToLoadItem
}
/**
Streamline loading of items of a given type in a given extension context.
- Parameters:
- type: The type of content to look for and load in the extension context.
This is likely a string from `UTCoreTypes.h`.
- Returns:
A publisher which will yield, an array of items of `T` type, or an error.
- Note:
When using the publisher produced you have to give an explicit type to the
closure parameter in order to specialize over the generic otherwise usages
will fail to compile.
Correct Usage:
```
context.items(for: kUTTypeText as String).sink(
receiveCompletion: { completion in
// do something with completion
},
receiveValue: { (value: [String]) in
// do something with the array of strings...
}).store(in: &storage)
```
*/
func items<T>(for type: String) -> AnyPublisher<[T], Error> {
// swiftlint:disable:next force_cast
let items = inputItems as! [NSExtensionItem]
return items.publisher.compactMap { items in
items.attachments
}.flatMap { attachments in
attachments.publisher
}.filter { publisher in
publisher.hasItemConformingToTypeIdentifier(type)
}.flatMap { publisher in
Future<T, Error> { promise in
publisher.loadItem(forTypeIdentifier: type, options: nil) { item, error in
if let error = error {
promise(.failure(error))
return
}
if let item = item as? T {
promise(.success(item))
return
}
// If for some reason we have reached here, return an error
// since no content, and no error were received.
promise(.failure(Errors.unableToLoadItem))
}
}
}
.collect()
.eraseToAnyPublisher()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment