Created
June 5, 2021 12:25
-
-
Save brianmichel/4b6e335222d1ee52e027f65d96447a3d to your computer and use it in GitHub Desktop.
Publisher-ify NSExtensionContext item loading
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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