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

Swift Combine订阅未触发问题:使用freshOS/Networking调用公共国家API无输出

问题诊断与修复方案

我帮你排查出几个关键问题,导致Combine订阅没触发、数据无法正常解析:

1. 订阅对象被提前销毁(最核心原因)

你在callAPI()里声明的var cancellable = Set<AnyCancellable>()是局部变量,当函数执行完毕后,这个集合会被立即释放,Combine的订阅也会随之取消,所以你永远看不到print的输出。

修复方法:把cancellable提升为ViewController的属性,让它能在ViewController的生命周期内保持存在:

class YourViewController: UIViewController {
    // 把cancellable移到类的属性位置
    private var cancellables = Set<AnyCancellable>()
    // ... 其他属性
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureUI()
        callAPI()
    }
    
    // ... 其他方法
}

2. API返回类型与Publisher声明不匹配

你的countries()函数声明返回AnyPublisher<[CountryModel], Error>(CountryModel的数组),但实际API返回的是单个CountryModel对象(不是数组)。这种类型不匹配会导致解码失败,即使订阅没被取消,也会走到failure分支,但因为之前的cancellable被销毁,你看不到错误信息。

修复方法:修改countries()的返回类型为单个CountryModel:

struct CountriesApi: NetworkingService {
    let network = NetworkingClient(baseURL: "https://countriesnow.space/api/v0.1")
    
    // ... 其他CRUD方法
    
    // 修改返回类型为单个CountryModel,不是数组
    func countries() -> AnyPublisher<CountryModel, Error> {
        get("/countries/iso")
    }
}

同时,更新callAPI()里的订阅闭包,适配新的返回类型:

fileprivate func callAPI() {
    let countriesService = CountriesApi()
    countriesService.countries().sink(receiveCompletion: { completion in
        switch completion {
        case .finished:
            print("finished")
        case .failure(let error):
            print("请求失败:\(error.localizedDescription)")
        }
    }) { countryModel in
        print(countryModel)
        self.countriesData = countryModel.data // 这里取data数组赋值给你的数据源
    }.store(in: &cancellables) // 注意这里用类属性cancellables
}

3. 模型的小细节确认(可选)

你的Country模型里的Iso3属性和API返回的"Iso3"key大小写一致,Codable可以正常解析;API返回的Iso2字段因为模型里没定义,会被自动忽略,这部分没问题。


把这些修改完成后,应该就能正常触发订阅、获取并解析国家列表了。

内容的提问来源于stack exchange,提问作者AhmedEls

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 11:24:20