You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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值导致类型推断失败:

  1. 服务器获取后的flatMap里,直接返回code(String?类型),但flatMap要求返回一个Publisher,不能直接返回原始值
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 09:50:25