Search code examples
iosswiftuitableviewuiactivityindicatorviewdispatch-async

Display UIActivityIndicator while loading API data safely


I'm working on this app and have developed a full API for it. However, now that I've come to the front end part (the IOS app), I'm not sure how to load that data the right way.

I have made this class to make requests a little bit easier, but I get confused when it comes to threading and that sort of stuff...

Basically, I have a simple UITableView set up, and I want it to display data that I fetch from my API. During fetching, I need it to display a UIActivityIndicator which has to hide automatically as well.

How the hell do I do this? (Especially the automatic UIActivityIndicator)

Here is my request struct:

//
//  Request.swift
//  Voots
//
//  Created by Carlo on 16/10/2017.
//  Copyright © 2017 Carlo. All rights reserved.
//

import Foundation

struct Request {

    // Post request with specific url, parameters and token
    func post(params: [String: String], url: String, token: String?, 
        completion: ((Data, URLResponse) -> ())?) {


        let nsUrl = NSURL(string: url)
        var request = URLRequest(url: nsUrl! as URL)

        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")

        // If a token was provided, add it.
        if token != nil {
            request.addValue("Bearer \(String(describing: token!))", forHTTPHeaderField: "Authorization")
            print(request.value(forHTTPHeaderField: "Authorization")!)

        }

        request.httpMethod = "POST"

        guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions.prettyPrinted) else {
            return
        }

        request.httpBody = httpBody

        let session = URLSession.shared
        session.dataTask(with: request) { (data, response, error) in

            if let data = data {
                if let response = response {
                    if completion != nil {
                        completion!(data, response)
                    }
                }
            }

        }.resume()

    }

    func get(url: String, token: String?, completion: ((Data, URLResponse) -> ())?) {
        let nsUrl = NSURL(string: url)
        var request = URLRequest(url: nsUrl! as URL)

        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")

        // If a token was provided, add it.
        if token != nil {
            request.addValue("Bearer \(String(describing: token!))", forHTTPHeaderField: "Authorization")
            print(request.value(forHTTPHeaderField: "Authorization")!)

        }

        request.httpMethod = "GET"

        let session = URLSession.shared
        session.dataTask(with: request) { (data, response, error) in

            if let data = data {
                if let response = response {
                    if completion != nil {
                        completion!(data, response)
                    }
                }
            }

            }.resume()
    }
}

Solution

  • Here is list of readymade (available) libraries, if you don't want to add manual effort to manage this:


    Here is sample for you, how you can manage it.

    class ViewController: UIViewController {
    
        // Create an IBOutlet of indicator or you can create it programatically also.
        @IBOutlet weak var activitIndicator: UIActivityIndicatorView!
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            activitIndicator.isHidden = false
            Request.post(params: <#T##[String : String]#>, url: <#T##String#>, token: <#T##String?#>) { (<#Data#>, <#URLResponse#>) in
                DispatchQueue.main.async(execute: {
                    self.activitIndicator.isHidden = true
                })
            }
    
        }
    }
    
    
    struct Request {
    
        // Post request with specific url, parameters and token
        // Note: use static function
        static func post(params: [String: String], url: String, token: String?,
                  completion: ((Data, URLResponse) -> ())?) {
    
    
            let nsUrl = NSURL(string: url)
            var request = URLRequest(url: nsUrl! as URL)
    
            request.addValue("application/json", forHTTPHeaderField: "Content-Type")
            request.addValue("application/json", forHTTPHeaderField: "Accept")
    
            // If a token was provided, add it.
            if token != nil {
                request.addValue("Bearer \(String(describing: token!))", forHTTPHeaderField: "Authorization")
                print(request.value(forHTTPHeaderField: "Authorization")!)
    
            }
    
            request.httpMethod = "POST"
    
            guard let httpBody = try? JSONSerialization.data(withJSONObject: params, options: JSONSerialization.WritingOptions.prettyPrinted) else {
                return
            }
    
            request.httpBody = httpBody
    
            let session = URLSession.shared
            session.dataTask(with: request) { (data, response, error) in
    
                if let data = data {
                    if let response = response {
                        if completion != nil {
                            completion!(data, response)
                        }
                    }
                }
    
                }.resume()
    
        }
    
        // Note: use static function
        static func get(url: String, token: String?, completion: ((Data, URLResponse) -> ())?) {
            let nsUrl = NSURL(string: url)
            var request = URLRequest(url: nsUrl! as URL)
    
            request.addValue("application/json", forHTTPHeaderField: "Content-Type")
            request.addValue("application/json", forHTTPHeaderField: "Accept")
    
            // If a token was provided, add it.
            if token != nil {
                request.addValue("Bearer \(String(describing: token!))", forHTTPHeaderField: "Authorization")
                print(request.value(forHTTPHeaderField: "Authorization")!)
    
            }
    
            request.httpMethod = "GET"
    
            let session = URLSession.shared
            session.dataTask(with: request) { (data, response, error) in
    
                if let data = data {
                    if let response = response {
                        if completion != nil {
                            completion!(data, response)
                        }
                    }
                }
    
                }.resume()
        }
    }