Combine Swift中flatMap块存字符串到数据库遇类型歧义错误求助
Combine flatMap 类型歧义错误修复
需求:在Interactor中实现逻辑:从本地数据库获取指定codeId的字符串,若未找到则从服务器获取该字符串,存入本地数据库后返回。数据库读写操作由单独文件处理。
原代码:
public func fetchCode(codeId: String) -> AnyPublisher<String?, Error> { //Get code from localdb codeStorageProvider.fetchCode(codeId).flatMap { (code) -> AnyPublisher<String?, Error> in if let code = code { return Just(code).mapError{ $0 as Error }.eraseToAnyPublisher() } //If not found in db, Get code from server let code = self.voucherCodeProvider.fetchVoucherCode(codeId: codeId) return code.flatMap { code in //save the code to local db self.codeStorageProvider.saveVoucherCode(code, codeId) return code }.eraseToAnyPublisher() //return code to presenter }.eraseToAnyPublisher() }
遇到错误:
Type of expression is ambiguous without more context
问题原因及修复方案
错误核心是flatMap闭包中返回的类型不统一,以及直接返回非Publisher值导致类型推断失败:
- 服务器获取后的flatMap里,直接返回
code(String?类型),但flatMap要求返回一个Publisher,不能直接返回原始值 saveVoucherCode的操作需要被包装进流中,确保整个链式调用的类型一致
修正后的代码:
public func fetchCode(codeId: String) -> AnyPublisher<String?, Error> { // 从本地数据库查询code codeStorageProvider.fetchCode(codeId) .flatMap { [weak self] code -> AnyPublisher<String?, Error> in guard let self = self else { return Fail(error: NSError(domain: "InteractorDeallocated", code: -1, userInfo: nil)) .eraseToAnyPublisher() } // 本地找到code,直接返回 if let code = code { return Just(code) .setFailureType(to: Error.self) .eraseToAnyPublisher() } // 本地未找到,请求服务器 return self.voucherCodeProvider.fetchVoucherCode(codeId: codeId) .flatMap { fetchedCode -> AnyPublisher<String?, Error> in // 保存到本地数据库,假设saveVoucherCode返回AnyPublisher<Void, Error> return self.codeStorageProvider.saveVoucherCode(fetchedCode, codeId) .map { _ in fetchedCode } // 保存成功后返回获取到的code .eraseToAnyPublisher() } .eraseToAnyPublisher() } .eraseToAnyPublisher() }
关键修正点:
- 增加
[weak self]避免循环引用,同时处理Interactor被提前释放的情况 - 本地返回分支用
setFailureType(to: Error.self)替代mapError,更简洁(Just本身不会产生错误,只需指定失败类型) - 服务器获取后的flatMap中,将
saveVoucherCode的结果通过map转换为要返回的fetchedCode,保证输出类型统一为String? - 所有分支严格返回
AnyPublisher<String?, Error>类型,消除Swift的类型推断歧义
内容的提问来源于stack exchange,提问作者pankaj
相关产品推荐
相关产品推荐

