Created
September 24, 2020 22:44
-
-
Save ericlewis/25310a719cba4f97e798aa5c238de77e to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| // | |
| // LPMetadataProvider+Combine.swift | |
| // Hacker | |
| // | |
| // Created by Eric Lewis on 9/22/20. | |
| // | |
| import SwiftUI | |
| import LinkPresentation | |
| import Combine | |
| class MetadataProvider: ObservableObject { | |
| @Published var metadata: LPLinkMetadata? | |
| @Published var image: UIImage? | |
| @Published var icon: UIImage? | |
| @Published var error: Error? | |
| var cancellable: AnyCancellable? | |
| var imageCancellable: AnyCancellable? | |
| var iconCancellable: AnyCancellable? | |
| private var provider = LPMetadataProvider() | |
| func fetch(url: URL) { | |
| error = nil | |
| cancellable = provider.startFetchingMetadataPublisher(for: url) | |
| .receive(on: RunLoop.main) | |
| .sink(receiveCompletion: { [weak self] completion in | |
| switch completion { | |
| case .finished: | |
| break | |
| case .failure(let error): | |
| self?.error = error | |
| } | |
| }) { [weak self] metadata in | |
| guard let `self` = self else { | |
| return | |
| } | |
| self.metadata = metadata | |
| self.imageCancellable = metadata?.imageProvider?.loadObjectPublisher(forClass: UIImage.self) | |
| .receive(on: RunLoop.main) | |
| .catch { _ in Just(nil) } | |
| .assign(to: \.image, on: self) | |
| self.iconCancellable = metadata?.iconProvider?.loadObjectPublisher(forClass: UIImage.self) | |
| .receive(on: RunLoop.main) | |
| .catch { _ in Just(nil) } | |
| .assign(to: \.icon, on: self) | |
| } | |
| } | |
| deinit { | |
| cancellable?.cancel() | |
| imageCancellable?.cancel() | |
| iconCancellable?.cancel() | |
| } | |
| } | |
| extension LPMetadataProvider { | |
| func startFetchingMetadataPublisher(for url: URL) -> AnyPublisher<LPLinkMetadata?, Error> { | |
| Future<LPLinkMetadata?, Error> { [weak self] completion in | |
| self?.startFetchingMetadata(for: url) { meta, error in | |
| guard let error = error else { | |
| return completion(.success(meta)) | |
| } | |
| completion(.failure(error)) | |
| } | |
| } | |
| .handleEvents(receiveCancel: { [weak self] in | |
| self?.cancel() | |
| }) | |
| .eraseToAnyPublisher() | |
| } | |
| } | |
| extension NSItemProvider { | |
| func loadObjectPublisher<T>(forClass: T.Type) -> AnyPublisher<T?, Error> where T: NSItemProviderReading { | |
| Future<T?, Error> { [weak self] completion in | |
| self?.loadObject(ofClass: T.self) { item, error in | |
| guard let error = error else { | |
| return completion(.success(item as? T)) | |
| } | |
| completion(.failure(error)) | |
| } | |
| } | |
| .eraseToAnyPublisher() | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment