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
相关产品推荐
相关产品推荐

