Skip to content

Instantly share code, notes, and snippets.

@munho
Forked from hertz315/URLSession tutorial .md
Created November 29, 2023 07:11
Show Gist options
  • Select an option

  • Save munho/fa6ee78fabba14e9574100dca8aa5c27 to your computer and use it in GitHub Desktop.

Select an option

Save munho/fa6ee78fabba14e9574100dca8aa5c27 to your computer and use it in GitHub Desktop.

Revisions

  1. @hertz315 hertz315 revised this gist Dec 9, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion URLSession tutorial .md
    Original file line number Diff line number Diff line change
    @@ -58,7 +58,7 @@ extension URLRequest {
    ## JSON
    ### From Dictionary to JSON object - 중요⭐️ 보통 POST 방식 json을 요청데이터로 넣을때 사용 httpBody
    ```swift
    guard let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: [.prettyPrinted]) else {
    guard let data = try? JSONSerialization.data(withJSONObject: dictionary, options: [.prettyPrinted]) else {
    // JSON serialization failed
    return
    }
  2. @hertz315 hertz315 revised this gist Dec 9, 2022. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions URLSession tutorial .md
    Original file line number Diff line number Diff line change
    @@ -56,9 +56,9 @@ extension URLRequest {
    }
    ```
    ## JSON
    ### From Data to JSON object - 중요⭐️ 보통 POST 방식 json을 요청데이터로 넣을때 사용 httpBody
    ### From Dictionary to JSON object - 중요⭐️ 보통 POST 방식 json을 요청데이터로 넣을때 사용 httpBody
    ```swift
    guard let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: []) else {
    guard let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: [.prettyPrinted]) else {
    // JSON serialization failed
    return
    }
  3. @hertz315 hertz315 revised this gist Dec 9, 2022. 1 changed file with 2 additions and 8 deletions.
    10 changes: 2 additions & 8 deletions URLSession tutorial .md
    Original file line number Diff line number Diff line change
    @@ -56,22 +56,16 @@ extension URLRequest {
    }
    ```
    ## JSON
    ### From JSON object to Data
    ```swift
    guard let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: []) else {
    // JSON serialization failed
    return
    }
    ```
    ### From Data to JSON object - 중요⭐️ 보통 POST 방식 json을 요청데이터로 넣을때 사용 httpBody
    ```swift
    guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
    guard let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: []) else {
    // JSON serialization failed
    return
    }
    ```



    # URLSession Cheatsheet 2번째

    출처
  4. @hertz315 hertz315 revised this gist Dec 9, 2022. No changes.
  5. @hertz315 hertz315 revised this gist Dec 9, 2022. No changes.
  6. @hertz315 hertz315 revised this gist Dec 9, 2022. 1 changed file with 13 additions and 12 deletions.
    25 changes: 13 additions & 12 deletions URLSession tutorial .md
    Original file line number Diff line number Diff line change
    @@ -84,19 +84,19 @@ guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else
    * RESTFul API
    * URLSession
    * URLSession.shared
    * JSONDecoder, JSONEncoder
    * URL
    * URLRequest
    * URLResponse
    * JSONDecoder(중요), JSONEncoder
    * URL - simple
    * URLRequest - URL에 플러스로 추가 세팅이 되어 있는것
    * URLResponse - 응답
    * HTTPURLResponse
    * Status Code
    * Status Code - HTTP 상태 코드 200번 대가 OK(서버 환경마다 다름)
    * Data
    * Codable
    * Encodable
    * Decodable
    * Codable - 인코더블이랑 디코더블이 합쳐진 타입에일리어스
    * Encodable - Class 나 Struct Json 객체로 만드는 것
    * Decodable - Json을 Class 나 Struct로 만드는것
    * HTTP methods: GET, POST, PUT, DELETE, PATCH, UPDATE
    * Asynchronous
    * Result
    * Asynchronous - 비동기처리 방식 Closure, Rx Observable, Combine Publisher, Async await
    * Result - 응답 성공 데이터랑 에러가 같이 있는 제네릭 Enum Class Result<성공데이터, 커스텀에러데이터>
    * @escaping closures
    * capture list e.g [weak self], [unowned self]
    * weak vs unowned
    @@ -132,15 +132,16 @@ guard let httpResponse = response as? HTTPURLResponse,
    }
    ```

    ## Converting `JSON` data to Swift objects
    ## Converting `JSON` data to Swift objects - 와꾸 맞추는 작업⭐️

    ```swift
    do {
    // 데이터 파싱
    let topLevelModel = try JSONDecoder().decode(TopLevelModel.self, from: jsonData)
    let modelObjects = topLevelModel.modelObjects
    completion(.success(modelObjects)
    } catch {
    // decoding error
    // decoding error : JSON -> Class, Struct 변경이 실패되었을때
    completion(.failure(error))
    }
    ```
  7. @hertz315 hertz315 revised this gist Dec 9, 2022. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion URLSession tutorial .md
    Original file line number Diff line number Diff line change
    @@ -63,7 +63,7 @@ guard let data = try? JSONSerialization.data(withJSONObject: jsonObject, options
    return
    }
    ```
    ### From Data to JSON object
    ### From Data to JSON object - 중요⭐️ 보통 POST 방식 json을 요청데이터로 넣을때 사용 httpBody
    ```swift
    guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
    // JSON serialization failed
  8. @hertz315 hertz315 created this gist Dec 9, 2022.
    232 changes: 232 additions & 0 deletions URLSession tutorial .md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,232 @@
    ## IOS URLSession API 호출 정리

    출처
    [link]https://github.com/timojaask/URLSession-Cheat-Sheet/blob/master/README.md

    ## Simple GET request
    ```swift
    URLSession.shared.dataTask(with: url) { (data, response, error) in
    guard let statusCode = (response as? HTTPURLResponse)?.statusCode else {
    // request failed
    return
    }
    // handle status code
    }.resume()
    ```
    ## Query parameters
    ```swift
    var urlComponents = URLComponents(string: "https://www.google.com")!
    urlComponents.queryItems = [
    URLQueryItem(name: "foo1", value: "bar"),
    URLQueryItem(name: "foo2", value: "baz")
    ]
    let url = urlComponents.url // https://www.google.com?foo1=bar&foo2=baz
    ```
    ### Extension example
    ```swift
    extension URL {
    init?(baseUrl: String, queryItems: [String: String]) {
    guard var urlComponents = URLComponents(string: baseUrl) else { return nil }
    urlComponents.queryItems = queryItems.map { URLQueryItem(name: $0.key, value: $0.value) }
    guard let finalUrlString = urlComponents.url?.absoluteString else { return nil }
    self.init(string: finalUrlString)
    }
    }
    ```
    ## Method, body and headers
    ```swift
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.httpBody = data
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("*/*", forHTTPHeaderField: "Accept")
    ```
    ### Extension example
    ```swift
    extension URLRequest {
    static func request(url: URL, headers: [String: String] = [:], method: String = "GET", data: Data? = nil) -> URLRequest {
    var request = URLRequest(url: url)
    request.httpMethod = method
    request.httpBody = data
    headers.forEach { header in
    request.addValue(header.value, forHTTPHeaderField: header.key)
    }
    return request
    }
    }
    ```
    ## JSON
    ### From JSON object to Data
    ```swift
    guard let data = try? JSONSerialization.data(withJSONObject: jsonObject, options: []) else {
    // JSON serialization failed
    return
    }
    ```
    ### From Data to JSON object
    ```swift
    guard let json = try? JSONSerialization.jsonObject(with: data, options: []) else {
    // JSON serialization failed
    return
    }
    ```


    # URLSession Cheatsheet 2번째

    출처
    [link]https://github.com/alexpaul/iOS-UIKit/blob/main/URLSession-Cheatsheet.md

    ## Vocabulary

    * 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

    ## Using a closure to capture the `Result` of the asynchronous network request

    `Result` type is an `enum` type that has two arguments, a `success` state and an `failure` state.

    ```swift
    func fetchWebData(completion: @escaping (Result<[ModelObject], Error>) -> ()) {
    // netowrking code here
    }
    ```

    ## Perform a GET request using `URLSession`

    `URLSession.shared` is a singleton instance on `URLSession` with basic networking configurations.

    ```swift
    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

    ```swift
    guard let httpResponse = response as? HTTPURLResponse,
    (200...299).contains(httpResponse.statusCode) else {
    print("bad status code")
    return
    }
    ```

    ## Converting `JSON` data to Swift objects

    ```swift
    do {
    let topLevelModel = try JSONDecoder().decode(TopLevelModel.self, from: jsonData)
    let modelObjects = topLevelModel.modelObjects
    completion(.success(modelObjects)
    } catch {
    // decoding error
    completion(.failure(error))
    }
    ```

    ## Using the `Codable` protocol to parse JSON to Swift model(s)

    ```swift
    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"
    }
    }
    ```

    ## The `CodingKeys` built-in `enum` type allows us to change JSON property names to our own custom names

    In this example we change `Countries` to a more Swift naming conventional name `countries`.

    ```swift
    struct CovidCountriesWrapper: Codable {
    let countries: [CountrySummary]

    // CodingKeys allows us to rename properties
    enum CodingKeys: String, CodingKey {
    case countries = "Countries"
    }
    }
    ```

    ## Completed API Client to fetch web data

    ```swift
    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()
    }
    ```