【问题标题】:Combine: Transform an AnyPublisher into a another AnyPublisher合并:将一个 AnyPublisher 转换为另一个 AnyPublisher
【发布时间】:2021-04-18 21:39:28
【问题描述】:

我想将发布者转换为另一个发布者,但出现错误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()
}

【问题讨论】:

  • 这能回答你的问题吗? stackoverflow.com/a/63281155/560942
  • 这里有很多问题,但首先 - 如果login 返回Bool 的发布者,您如何处理result 就像它是Result 类型一样?

标签: swift combine


【解决方案1】:

您似乎想使用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
}

由于您想将错误转换为LoginStates,让我们添加一个初始化程序来执行此操作:

extension LoginState {
    public init(_ repoError: LoginRepositoryError) {
        switch repoError {
        case .wrongPassword: self = .wrongPassword
        case .userNotExist: self = .error
        case .emailValidationPending: self = .emailValidationPending
        }
    }
}

由于LoginUseCase.loginOutputBool,我们还要添加一个初始化器来将Bool 转换为LoginState

extension LoginState {
    public init(success: Bool) {
        self = success ? .success : .error
    }
}

现在我们可以将这些初始化程序与mapcatch 运算符一起使用来创建您正在寻找的AnyPublisher&lt;LoginState, Never&gt;

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: $0) }
            .catch { Just(LoginState(error: $0)) }
            .eraseToAnyPublisher()
    }
}

【讨论】:

  • 感谢您的精彩解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多