Reputation: 728
Recently, I tried to use freshOS/Networking swift package.
And I read the README file several times and I couldn't make it work with me. I'm trying to get a list of countries using public API services and here's what I did:
Model
import Foundation
import Networking
struct CountryModel: Codable {
let error: Bool
let msg: String
let data: [Country]
}
struct Country: Codable {
let name: String
let Iso3: String
}
extension Country: NetworkingJSONDecodable {}
extension CountryModel: NetworkingJSONDecodable {}
/*
Output
{
"error":false,
"msg":"countries and ISO codes retrieved",
"data":[
{
"name":"Afghanistan",
"Iso2":"AF",
"Iso3":"AFG"
}
]
}
*/
View Controller + print(data) in callAPI()
function does not print
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
callAPI()
}
fileprivate func configureUI() {
title = "Choose Country"
view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.frame = view.bounds
}
fileprivate func callAPI() {
let countriesService = CountriesApi()
var cancellable = Set<AnyCancellable>()
countriesService.countries().sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("finished") // not printing
break
case .failure(let error):
print(error.localizedDescription)
}
}) { data in
print(data) // not printing
self.countriesData = data
}.store(in: &cancellable)
}
CountriesAPI()
struct CountriesApi: NetworkingService {
let network = NetworkingClient(baseURL: "https://countriesnow.space/api/v0.1")
// Create
func create(country c: Country) -> AnyPublisher<Country, Error> {
post("/countries/create", params: ["name" : c.name, "Iso3" : c.Iso3])
}
// Read
func fetch(country c: Country) -> AnyPublisher<Country, Error> {
get("/countries/\(c.Iso3)")
}
// Update
func update(country c: Country) -> AnyPublisher<Country, Error> {
put("/countries/\(c.Iso3)", params: ["name" : c.name, "Iso3" : c.Iso3])
}
// Delete
func delete(country c: Country) -> AnyPublisher<Void, Error> {
delete("/countries/\(c.Iso3)")
}
func countries() -> AnyPublisher<[CountryModel], Error> {
get("/countries/iso")
}
}
I hope someone can help with what I'm missing.
Upvotes: 2
Views: 1225
Reputation: 1678
The problem lies in your callAPI()
function, if you change your code to this:
fileprivate func callAPI() {
let countriesService = CountriesApi()
var cancellable = Set<AnyCancellable>()
countriesService.countries()
.print("debugging")
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("finished") // not printing
break
case .failure(let error):
print(error.localizedDescription)
}
}) { data in
print(data) // not printing
self.countriesData = data
}.store(in: &cancellable)
}
Notice I just added the line print("debugging")
.
If you run that, you can see in your console that your subscription gets cancelled immediately.
debugging: receive cancel
Why? Because your "cancellable" or "subscription" only lives in the scope of your function, thus, it is deallocated immediately.
What you can do is add the cancellables set as a property in your ViewController, like this:
final class ViewController: UIViewController {
private var cancellable = Set<AnyCancellable>()
fileprivate func callAPI() {
// the code you had without the set
let countriesService = CountriesApi()
countriesService.countries().sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("finished") // not printing
break
case .failure(let error):
print(error.localizedDescription)
}
}) { data in
print(data) // not printing
self.countriesData = data
}.store(in: &cancellable)
}
}
Upvotes: 3