合并:将 AnyPublisher 转换为另一个 AnyPublisher
Combine: Transform an AnyPublisher into a another AnyPublisher
我想将 Publisher 转换为另一个 Publisher,但出现错误 Cannot convert return expression of type 'AnyPublisher<LoginState, LoginRepositoryError>' to return type 'AnyPublisher<LoginState, Never>'
我的方法可行吗,我有如下代码:
public protocol LoginUseCase {
func login(email: String, password: String) -> AnyPublisher<Bool, LoginRepositoryError>
}
MyViewmodel.swift
public func login(email: String?, password: String?) -> AnyPublisher<LoginState, Never> {
guard let email=email, !email.isEmpty else {
return Just<LoginState>(.invalidEmail).eraseToAnyPublisher()
}
guard let password=password, !password.isEmpty else {
return Just<LoginState>(.invalidPassword).eraseToAnyPublisher()
}
return loginUseCase.login(email: email, password: password)
.map { result in
let subject = PassthroughSubject<LoginState, Never>()
switch result {
case .success(_):
subject.send(.success)
break
case .failure(let error):
switch error {
case .wrongPassword:
subject.send(.wrongPassword)
case .userNotExist:
subject.send(.error)
case .emailValidationPending:
subject.send(.emailValidationPending)
}
}
return subject.eraseToAnyPublisher()
}.eraseToAnyPublisher()
}
您似乎想使用 catch
运算符将 failure
完成转换为 LoginState
。
我猜你有这样的enum LoginRepositoryError
:
public enum LoginRepositoryError: Error {
case wrongPassword
case userNotExist
case emailValidationPending
}
你有这样的enum LoginState
:
public enum LoginState {
case success
case invalidEmail
case invalidPassword
case wrongPassword
case error
case emailValidationPending
}
由于您想将错误转换为 LoginState
s,让我们添加一个初始化程序来执行此操作:
extension LoginState {
public init(_ repoError: LoginRepositoryError) {
switch repoError {
case .wrongPassword: self = .wrongPassword
case .userNotExist: self = .error
case .emailValidationPending: self = .emailValidationPending
}
}
}
并且由于 LoginUseCase.login
的 Output
是 Bool
,我们还要添加一个初始化程序以将 Bool
转换为 LoginState
:
extension LoginState {
public init(success: Bool) {
self = success ? .success : .error
}
}
现在我们可以将这些初始值设定项与 map
和 catch
运算符一起使用来创建您正在寻找的 AnyPublisher<LoginState, Never>
:
extension LoginUseCase {
public func loginState(withEmail email: String?, password: String?) -> AnyPublisher<LoginState, Never> {
guard let email=email, !email.isEmpty else {
return Just<LoginState>(.invalidEmail).eraseToAnyPublisher()
}
guard let password=password, !password.isEmpty else {
return Just<LoginState>(.invalidPassword).eraseToAnyPublisher()
}
return login(email: email, password: password)
.map { LoginState(success: [=14=]) }
.catch { Just(LoginState(error: [=14=])) }
.eraseToAnyPublisher()
}
}
我想将 Publisher 转换为另一个 Publisher,但出现错误 Cannot convert return expression of type 'AnyPublisher<LoginState, LoginRepositoryError>' to return type 'AnyPublisher<LoginState, Never>'
我的方法可行吗,我有如下代码:
public protocol LoginUseCase {
func login(email: String, password: String) -> AnyPublisher<Bool, LoginRepositoryError>
}
MyViewmodel.swift
public func login(email: String?, password: String?) -> AnyPublisher<LoginState, Never> {
guard let email=email, !email.isEmpty else {
return Just<LoginState>(.invalidEmail).eraseToAnyPublisher()
}
guard let password=password, !password.isEmpty else {
return Just<LoginState>(.invalidPassword).eraseToAnyPublisher()
}
return loginUseCase.login(email: email, password: password)
.map { result in
let subject = PassthroughSubject<LoginState, Never>()
switch result {
case .success(_):
subject.send(.success)
break
case .failure(let error):
switch error {
case .wrongPassword:
subject.send(.wrongPassword)
case .userNotExist:
subject.send(.error)
case .emailValidationPending:
subject.send(.emailValidationPending)
}
}
return subject.eraseToAnyPublisher()
}.eraseToAnyPublisher()
}
您似乎想使用 catch
运算符将 failure
完成转换为 LoginState
。
我猜你有这样的enum LoginRepositoryError
:
public enum LoginRepositoryError: Error {
case wrongPassword
case userNotExist
case emailValidationPending
}
你有这样的enum LoginState
:
public enum LoginState {
case success
case invalidEmail
case invalidPassword
case wrongPassword
case error
case emailValidationPending
}
由于您想将错误转换为 LoginState
s,让我们添加一个初始化程序来执行此操作:
extension LoginState {
public init(_ repoError: LoginRepositoryError) {
switch repoError {
case .wrongPassword: self = .wrongPassword
case .userNotExist: self = .error
case .emailValidationPending: self = .emailValidationPending
}
}
}
并且由于 LoginUseCase.login
的 Output
是 Bool
,我们还要添加一个初始化程序以将 Bool
转换为 LoginState
:
extension LoginState {
public init(success: Bool) {
self = success ? .success : .error
}
}
现在我们可以将这些初始值设定项与 map
和 catch
运算符一起使用来创建您正在寻找的 AnyPublisher<LoginState, Never>
:
extension LoginUseCase {
public func loginState(withEmail email: String?, password: String?) -> AnyPublisher<LoginState, Never> {
guard let email=email, !email.isEmpty else {
return Just<LoginState>(.invalidEmail).eraseToAnyPublisher()
}
guard let password=password, !password.isEmpty else {
return Just<LoginState>(.invalidPassword).eraseToAnyPublisher()
}
return login(email: email, password: password)
.map { LoginState(success: [=14=]) }
.catch { Just(LoginState(error: [=14=])) }
.eraseToAnyPublisher()
}
}