将 nil 替换为 Empty 或 Combine 中的 Error
Replace nil with Empty or Error in Combine
我有这样的 Combine 发布商:
enum RemoteError: Error {
case networkError(Error)
case parseError(Error)
case emptyResponse
}
func getPublisher(url: URL) -> AnyPublisher<Entiy, RemoteError> {
return URLSession.shared
.dataTaskPublisher(for: url)
.map(\.data)
.decode(type: RemoteResponse.self, decoder: decoder)
.mapError { error -> RemoteError in
switch error {
case is URLError:
return .networkError(error)
default:
return .parseError(error)
}
}
.map { response -> Entiy in
response.enitities.last
}
.eraseToAnyPublisher()
}
struct RemoteResponse: Codable {
let enitities: [Entity]
let numberOfEntries: Int
}
struct Entity {
}
通过上述设置,编译器会报错,因为 response.enitities.last
可以为 nil。问题是我可以用 Empty publisher 替换 nil 吗?如果不能,我可以用 Combine 链中的 error emptyResponse
替换它吗?第一个选项更可取。
您需要一个平面地图才能映射到另一个发布者:
.flatMap {
[=10=].enitities.last.publisher
}
Optional
有一个方便的 publisher
属性 ,它给你一个发布者,如果值不为 nil 则只发布该值,如果为 nil 则为空发布者。这仅适用于 iOS 14+。如果您的目标是较低版本,则需要执行以下操作:
.flatMap { (response) -> AnyPublisher<Entity, Never> in
if let last = response.entities.last {
return Just(last).eraseToAnyPublisher()
} else {
return Empty(completeImmediately: true).eraseToAnyPublisher()
}
}
这里有几个选项。
如果您不希望发布者在实体为空的情况下发布任何内容,您可以使用 coampactMap
而不是地图:
.compactMap { response in
response.entities.last
}
如果您更愿意在这种情况下发布错误,您可以使用 tryMap
,它允许您抛出 Error
。您需要 mapError
才能跟上它:
.tryMap { response in
guard let entity = response.entities.last else {
throw RemoteError.emptyResponse
}
return entity
}
.mapError { error -> RemoteError in
switch error {
case is URLError:
return .networkError(error)
case is DecodingError:
return .parseError(error)
default:
return .emptyResponse
}
}
我有这样的 Combine 发布商:
enum RemoteError: Error {
case networkError(Error)
case parseError(Error)
case emptyResponse
}
func getPublisher(url: URL) -> AnyPublisher<Entiy, RemoteError> {
return URLSession.shared
.dataTaskPublisher(for: url)
.map(\.data)
.decode(type: RemoteResponse.self, decoder: decoder)
.mapError { error -> RemoteError in
switch error {
case is URLError:
return .networkError(error)
default:
return .parseError(error)
}
}
.map { response -> Entiy in
response.enitities.last
}
.eraseToAnyPublisher()
}
struct RemoteResponse: Codable {
let enitities: [Entity]
let numberOfEntries: Int
}
struct Entity {
}
通过上述设置,编译器会报错,因为 response.enitities.last
可以为 nil。问题是我可以用 Empty publisher 替换 nil 吗?如果不能,我可以用 Combine 链中的 error emptyResponse
替换它吗?第一个选项更可取。
您需要一个平面地图才能映射到另一个发布者:
.flatMap {
[=10=].enitities.last.publisher
}
Optional
有一个方便的 publisher
属性 ,它给你一个发布者,如果值不为 nil 则只发布该值,如果为 nil 则为空发布者。这仅适用于 iOS 14+。如果您的目标是较低版本,则需要执行以下操作:
.flatMap { (response) -> AnyPublisher<Entity, Never> in
if let last = response.entities.last {
return Just(last).eraseToAnyPublisher()
} else {
return Empty(completeImmediately: true).eraseToAnyPublisher()
}
}
这里有几个选项。
如果您不希望发布者在实体为空的情况下发布任何内容,您可以使用 coampactMap
而不是地图:
.compactMap { response in
response.entities.last
}
如果您更愿意在这种情况下发布错误,您可以使用 tryMap
,它允许您抛出 Error
。您需要 mapError
才能跟上它:
.tryMap { response in
guard let entity = response.entities.last else {
throw RemoteError.emptyResponse
}
return entity
}
.mapError { error -> RemoteError in
switch error {
case is URLError:
return .networkError(error)
case is DecodingError:
return .parseError(error)
default:
return .emptyResponse
}
}