본문 바로가기
Programming/Swift

[Readable Coding Practice] Fetching data from REST API with URLSession

by Eisen Sophie 2021. 6. 18.

In order to provide data from network, I usually use singleton class.

In the class I make a data fetching function.

Coding this function usually gets messy and hard to read.

I used enum to make codes in the function more readable.

 

 

class NetworkManager {
    static let shared = NetworkManager()
    let baseUrl = "http://api.github.com/users/"
    private init(){ }
    
    func getFollowers(for username: String, page: Int, completionHandler: @escaping (Result<[Follower]?, GFError>) -> Void) {
        let endPoint = baseUrl + "\(username)/followers?per_page=100&page=\(page)"
        
        guard let url = URL(string: endPoint) else { return completionHandler(.failure(.invalidUsername))}
        
        URLSession.shared.dataTask(with: url) { data, response, error in
            
            if let _ = error{
                completionHandler(.failure(.unableToComplete))
                return
            }
            
            guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
                completionHandler(.failure(.invalidResponse))
                return
            }
            
            guard let data = data else {
                completionHandler(.failure(.invalidData))
                return
            }
            
            do {
                let decode = JSONDecoder()
                decode.keyDecodingStrategy = .convertFromSnakeCase
                let followers = try decode.decode([Follower].self, from: data)
                completionHandler(.success(followers))
            } catch {
                completionHandler(.failure(.invalidData))
            }
            
        }.resume()
    }
}

 

enum GFError: String, Error {
    case invalidUsername = "invalid username"
    case unableToComplete = "unable to complete"
    case invalidResponse = "invalid response"
    case invalidData = "invalid data"
}

 

 

This code below here is when the singleton class is called in viewcontroller.

 

 

 NetworkManager.shared.getFollowers(for: username, page: 1) { result in
            switch result{
            case .success(let followers):
                print(followers)
                break
                
            case .failure(let error):
                self.presentGFAkertOnMainThread(title: "Error", message: error.rawValue ?? "", buttonTitle: "Ok")
                break
            }
        }