mirror of
https://github.com/ivanvorobei/SwiftUI.git
synced 2026-04-10 19:17:07 +02:00
Combine examples
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// AnySubscription.swift
|
||||
// GitHubSearchWithSwiftUI
|
||||
//
|
||||
// Created by John Holdsworth on 09/07/2019.
|
||||
// Copyright © 2019 jp.marty-suzuki. All rights reserved.
|
||||
//
|
||||
|
||||
import Combine
|
||||
|
||||
/// - seealso: https://twitter.com/peres/status/1135970931153821696
|
||||
final class AnySubscription: Subscription {
|
||||
|
||||
private let cancellable: AnyCancellable
|
||||
|
||||
init(_ cancel: @escaping () -> Void) {
|
||||
self.cancellable = AnyCancellable(cancel)
|
||||
}
|
||||
|
||||
func request(_ demand: Subscribers.Demand) {}
|
||||
|
||||
func cancel() {
|
||||
cancellable.cancel()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// ErrorResponse.swift
|
||||
// GitHubSearchWithSwiftUI
|
||||
//
|
||||
// Created by John Holdsworth on 09/07/2019.
|
||||
// Copyright © 2019 jp.marty-suzuki. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct ErrorResponse: Decodable, Error {
|
||||
let message: String
|
||||
}
|
||||
@@ -10,27 +10,42 @@ import Combine
|
||||
import Foundation
|
||||
|
||||
enum RepositoryAPI {
|
||||
typealias SearchResponse = AnyPublisher<Result<[Repository], ErrorResponse>, Never>
|
||||
typealias SendRequest = (URLRequest) -> AnyPublisher<Data, URLSessionError>
|
||||
|
||||
static func search(query: String) -> AnyPublisher<[Repository], Error> {
|
||||
static func search(query: String) -> SearchResponse {
|
||||
search(query: query, sendRequest: URLSession.shared.combine.send)
|
||||
}
|
||||
|
||||
static func search(query: String, sendRequest: SendRequest) -> SearchResponse {
|
||||
|
||||
guard var components = URLComponents(string: "https://api.github.com/search/repositories") else {
|
||||
return Publishers.Empty<[Repository], Error>().eraseToAnyPublisher()
|
||||
return .empty()
|
||||
}
|
||||
components.queryItems = [URLQueryItem(name: "q", value: query)]
|
||||
|
||||
guard let url = components.url else {
|
||||
return Publishers.Empty<[Repository], Error>().eraseToAnyPublisher()
|
||||
return .empty()
|
||||
}
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
let decoder = JSONDecoder()
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
return URLSession.shared.combine.send(request: request)
|
||||
return sendRequest(request)
|
||||
.decode(type: ItemResponse<Repository>.self, decoder: decoder)
|
||||
.map { $0.items }
|
||||
.handleEvents(receiveOutput: { print($0) },
|
||||
receiveCompletion: { print($0)})
|
||||
.map { Result<[Repository], ErrorResponse>.success($0.items) }
|
||||
.catch { error -> SearchResponse in
|
||||
guard case let .serverErrorMessage(_, data)? = error as? URLSessionError else {
|
||||
return .just(.success([]))
|
||||
}
|
||||
do {
|
||||
let response = try JSONDecoder().decode(ErrorResponse.self, from: data)
|
||||
return .just(.failure(response))
|
||||
} catch _ {
|
||||
return .just(.success([]))
|
||||
}
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user