I am having issues trying to get this data. I heard there is a trick. Can anyone create a simple call to view the data from this api? Would truly appreciate it. Been trying for a week. I cant for the life of me get this simple api call to work.
http://api.citybik.es/v2/networks
Model.swift
import Foundation
// MARK: - Welcome
struct Dataset: Codable {
let networks: [Network]
}
// MARK: - Network
struct Network: Codable {
let company: [String]
let href, id: String
let location: Location
let name: String
}
// MARK: - Location
struct Location: Codable {
let city, country: String
let latitude, longitude: Double
}
Contentview.swift
import SwiftUI
struct ContentView: View {
@State var results = [Network]()
func loadData() {
guard let url = URL(string: "http://api.citybik.es/v2/networks") else {
print("Your API end point is Invalid")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
if let response = try? JSONDecoder().decode([Network].self, from: data) {
DispatchQueue.main.async {
self.results = response
}
return
}
}
}.resume()
}
var body: some View {
List(results, id: \.name) { item in
VStack(alignment: .leading) {
Text("\(item.name)")
}
}.onAppear(perform: loadData)
}
}
copy the whole of the json from : "https://api.citybik.es/v2/networks" into "https://app.quicktype.io/" and get the (correct) swift data structures from that. Rename "Welcome" to "Response" and use that in your code.
use: "https://api.citybik.es/v2/networks" note the https.
EDIT: In your code:
struct ContentView: View {
@State var networks = [Network]()
var body: some View {
List(networks, id: \.id) { network in
VStack {
Text(network.name)
Text(network.location.city)
}
}.onAppear(perform: loadData)
}
func loadData() {
guard let url = URL(string: "https://api.citybik.es/v2/networks") else {
print("Your API end point is Invalid")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
if let response = try? JSONDecoder().decode(Response.self, from: data) {
DispatchQueue.main.async {
self.networks = response.networks
}
return
}
}
}.resume()
}
}
Once you have all the data structures, and if you are using Swift 5.5 for ios 15 or macos 12, you can use something like this:
struct ContentView: View {
@State var networks = [Network]()
var body: some View {
List(networks, id: \.id) { network in
VStack {
Text(network.name)
Text(network.location.city)
}
}
.task {
let response: Response? = await fetchNetworks()
if let resp = response {
networks = resp.networks
}
}
}
func fetchNetworks<T: Decodable>() async -> T? {
let url = URL(string: "https://api.citybik.es/v2/networks")!
let request = URLRequest(url: url)
do {
let (data, response) = try await URLSession.shared.data(for: request)
guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
// throw URLError(.badServerResponse) // todo
print(URLError(.badServerResponse))
return nil
}
let results = try JSONDecoder().decode(T.self, from: data)
return results
}
catch {
return nil
}
}
}