Created
November 10, 2021 06:28
-
-
Save trickart/d7cab1b8ae7ca1ebe13a5c1c66a219f9 to your computer and use it in GitHub Desktop.
CombineでURLSessionを連結するやつ
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
import SwiftUI | |
import Combine | |
let decoder: JSONDecoder = { | |
let decoder = JSONDecoder() | |
decoder.keyDecodingStrategy = .convertFromSnakeCase | |
return decoder | |
}() | |
struct User: Decodable, Equatable, Hashable { | |
let login: String | |
let id: Int | |
let avatarUrl: URL | |
} | |
enum UsersError: Error { | |
case empty | |
} | |
struct UsersPublisher { | |
let request: URLRequest = { | |
var request = URLRequest(url: URL(string: "https://api.github.com/users")!) | |
request.httpMethod = "GET" | |
request.allHTTPHeaderFields = ["Accept": "application/vnd.github.v3+json"] | |
return request | |
}() | |
func publish() -> AnyPublisher<[User], Error> { | |
URLSession.shared | |
.dataTaskPublisher(for: request) | |
.map(\.data) | |
.decode(type: [User].self, decoder: decoder) | |
.eraseToAnyPublisher() | |
} | |
} | |
enum ImageError: Error { | |
case url(URLError) | |
case other | |
} | |
struct ImagePublisher { | |
let url: URL | |
func publish() -> AnyPublisher<UIImage, Error> { | |
URLSession.shared | |
.dataTaskPublisher(for: url) | |
.map { UIImage(data: $0.data)! } | |
// 連結するときFailureの型が一致しないとダメっぽい | |
// https://stackoverflow.com/questions/66713123/why-cant-i-use-flatmap-after-trymap-in-swift-combine/66715459#66715459 | |
.mapError { $0 as Error } | |
.eraseToAnyPublisher() | |
} | |
} | |
var cancellables: Set<AnyCancellable> = [] | |
UsersPublisher().publish() | |
.tryMap { users -> URL in | |
guard let first = users.first else { | |
throw UsersError.empty | |
} | |
return first.avatarUrl | |
} | |
.flatMap { url in | |
ImagePublisher(url: url).publish() | |
} | |
.sink(receiveCompletion: { print($0) }, receiveValue: { print($0) }) | |
.store(in: &cancellables) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment