- JSON
- endpoint
- RESTFul API
- URLSession
- URLSession.shared
- JSONDecoder, JSONEncoder
- URL
- URLRequest
- URLResponse
- HTTPURLResponse
- Status Code
- Data
- Codable
- Encodable
- Decodable
- HTTP methods: GET, POST, PUT, DELETE, PATCH, UPDATE
- Asynchronous
- Result
- @escaping closures
- capture list e.g [weak self], [unowned self]
- weak vs unowned
Result type is an enum type that has two arguments, a success state and an failure state.
func fetchWebData(completion: @escaping (Result<[ModelObject], Error>) -> ()) {
// netowrking code here
}URLSession.shared is a singleton instance on URLSession with basic networking configurations.
let dataTask = URLSession.shared.dataTask(with: url) { (data, response, error) in
// networking code here
}
dataTask.resume()Check that the HTTPURLResponse status code is within the valid range of 200...299 indicating a successful response
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("bad status code")
return
}do {
let topLevelModel = try JSONDecoder().decode(TopLevelModel.self, from: jsonData)
let modelObjects = topLevelModel.modelObjects
completion(.success(modelObjects)
} catch {
// decoding error
completion(.failure(error))
}struct CovidCountriesWrapper: Codable {
let countries: [CountrySummary]
// CodingKeys allows us to rename properties
enum CodingKeys: String, CodingKey {
case countries = "Countries"
}
}
struct CountrySummary: Codable {
let country: String
let totalConfirmed: Int
let totalRecovered: Int
enum CodingKeys: String, CodingKey {
case country = "Country"
case totalConfirmed = "TotalConfirmed"
case totalRecovered = "TotalRecovered"
}
}In this example we change Countries to a more Swift naming conventional name countries.
struct CovidCountriesWrapper: Codable {
let countries: [CountrySummary]
// CodingKeys allows us to rename properties
enum CodingKeys: String, CodingKey {
case countries = "Countries"
}
} func fetchWebData(completion: @escaping (Result<[ModelObject], Error>) -> ()) {
// 1. - endpoint URL string
let endpointURLString = "https://........"
// 2. - convert the string to an URL
guard let url = URL(string: endpointURLString) else {
print("bad url")
return
}
// URL vs URLRequest
// 3. - make the request using URLSession
// .shared is an singleton instance on URLSession comes with basic configuration needed for most requests
let dataTask = URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error = error {
return completion(.failure(error))
}
// first we have to type cast URLResponse to HTTPURLRepsonse to get access to the status code
// we verify the that status code is in the 200 range which signals all went well with the GET request
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
print("bad status code")
return
}
if let jsonData = data {
// convert data to our swift model
do {
let topLevelModel = try JSONDecoder().decode(TopLevelModel.self, from: jsonData)
let modelObjects = topLevelModel.modelObjects
completion(.success(modelObjects))
} catch {
// decoding error
completion(.failure(error))
}
}
}
dataTask.resume()
}