【问题标题】:How to implement my MVP / Rxswift with Combine如何使用 Combine 实现我的 MVP/Rxswift
【发布时间】:2025-11-29 09:00:02
【问题描述】:

通常我会这样组织我的代码(以简化的方式):

演示者订阅我的模型(通过经理)

myManager.getItems(...).subscribe { .... }.disposed()

Manager 从 Provider 调用 getItems 并转换 DTO -> BO :

func getItems(...) -> Single<myObectBO> {
    myProvider.getItems(...).map { myDTO in
        return MyObjectBO(withDTO: myDTO)
    }
}

Provider 返回一个 DTO 的 Single:

func getItems(...) -> Single<myObectDTO> {
    ...
    return Single.just(myObectDTO)
}

我尝试了不同的方法,但目前我没有发现在 Combine 中实现它,有没有简单的方法可以做到这一点? 感谢您的帮助。


为了更清楚,我想做这样的事情:

func getSomething() {
    getManagerFuture()
        .sink { result in
            print(result)
        }
}

func getManagerFuture() -> Future<[MyBO], ManagerError> {
    
    Future { promise in
    getProviderFuture()
        .flatMap { dtoList -> ([MyBO], ManagerError) in
            
            let boList = dtoList.map { dto in
                return MyBO(id: dto.id, name: dto.name)
            }
            
            return promise(.success(boList))
        }
    }
}

func getProviderFuture() -> Future<[MyDTO], ProviderError> {

    // should be a webservice call
    
    let dto1 = MyDTO(id: 1, name: "one")
    let dto2 = MyDTO(id: 2, name: "two")
    
    return Future { promise in promise(.success([dto1, dto2])) }
}

我在 getManagerProvider 上有这个错误:

实例方法 'flatMap(maxPublishers:_:)' 需要类型 '([MyBO], ManagerError).Failure' 和 'Never' 是等价的

类型 '([MyBO], ManagerError)' 不能符合 'Publisher';只要 struct/enum/class 类型可以符合协议

【问题讨论】:

  • 具体实现什么?并发症到底在哪里?

标签: swift rx-swift combine


【解决方案1】:

我有这样的东西,在操场上很好用。

为了精确起见,最好删除发布者,以便能够在不更改代码外部的情况下更改实现

enum DTOError: Error {
  case wrongDTO
}

enum BOError: Error {
  case wrongBO
}

struct DTO {
  let value = "Value"
}

struct BO {
  let value: String
  init(dto: DTO) {
    self.value = dto.value
  }
}

func getDTO() -> AnyPublisher<DTO, DTOError> {
  Future { promise in
    promise(.success(DTO()))
  }
  .eraseToAnyPublisher()
}

func getBO() -> AnyPublisher<BO, BOError> {
  getDTO()
    .flatMap({ dto -> Future<BO, DTOError> in
      Future<BO, DTOError> { promise in
        promise(.success(BO(dto: dto)))
      }
    })
    .mapError { dtoError -> BOError in
      .wrongBO
    }
    .eraseToAnyPublisher()
}

getBO()
  .sink(receiveCompletion: { completion in
    print(completion)
  }) { data in
    print(data)
  }

可能有更简洁的解决方案

【讨论】: