Recently I have started learning iOS app development using swift so I am new to it. I want to implement rest api call in swift & found that we can achieve this using URLRequest
. So I have written generic method
to call all type(like get, put, post
) of rest api as below.
import Foundation
//import Alamofire
public typealias JSON = [String: Any]
public typealias HTTPHeaders = [String: String];
public enum RequestMethod: String {
case get = "GET"
case post = "POST"
case put = "PUT"
case delete = "DELETE"
}
public enum Result<Value> {
case success(Value)
case failure(Error)
}
public class apiClient{
private var base_url:String = "https://api.testserver.com/"
private func apiRequest(endPoint: String,
method: RequestMethod,
body: JSON? = nil,
token: String? = nil,
completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) {
let url = URL(string: (base_url.self + endPoint))!
var urlRequest = URLRequest(url: url)
urlRequest.httpMethod = method.rawValue
urlRequest.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
if let token = token {
urlRequest.setValue("bearer " + token, forHTTPHeaderField: "Authorization")
}
if let body = body {
urlRequest.httpBody = try? JSONSerialization.data(withJSONObject: body)
}
let session = URLSession(configuration: .default)
let task = session.dataTask(with: urlRequest) { data, response, error in
//NSLog(error)
completionHandler(data, response, error)
}
task.resume()
}
public func sendRequest<T: Decodable>(for: T.Type = T.self,
endPoint: String,
method: RequestMethod,
body: JSON? = nil,
token: String? = nil,
completion: @escaping (Result<T>) -> Void) {
return apiRequest(endPoint: endPoint, method: method, body:body, token: token) { data, response, error in
guard let data = data else {
return completion(.failure(error ?? NSError(domain: "SomeDomain", code: -1, userInfo: nil)))
}
do {
let decoder = JSONDecoder()
try completion(.success(decoder.decode(T.self, from: data)))
} catch let decodingError {
completion(.failure(decodingError))
}
}
}
}
this is how I call it method from controller
public func getProfile(userId :Int, objToken:String) -> Void {
let objApi = apiClient()
objApi.sendRequest(for: ProfileDetails.self,
endPoint:"api/user/profile/\(userId)",
method: .get,
token: objToken,
completion:
{(userResult: Result<ProfileDetails>) -> Void in
switch userResult
{
case .success(let value):
if value.respCode == "01" {
print(value.profile)
do {
//... ddo some taks like store response in local db or else
} catch let error as NSError {
// handle error
print(error)
}
}
else {
//do some task
}
break
case .failure(let error):
print(error)
break
}
})
}
I am decoding server response in below model
class ProfileDetails : Response, Decodable {
var appUpdate : AppUpdate?
var profile : Profile?
enum CodingKeys: String, CodingKey {
case profile = "profile"
case respCode = "resp_code"
case respMsg = "resp_msg"
}
public required convenience init(from decoder: Decoder) throws {
self.init()
let values = try decoder.container(keyedBy: CodingKeys.self)
self.profile = try values.decodeIfPresent(Profile.self, forKey: .profile)
self.respCode = try values.decodeIfPresent(String.self, forKey: .respCode)!
self.respMsg = try values.decodeIfPresent(String.self, forKey: .respMsg)
}
}
This code is not able to handle error response like 401, 404
etc from server. So what I am looking for, is to convert this api (URLRequest
)request to generic Alamofire
request with error handling like 401, 404
etc. I have install Alamofire
pods. Is there anyone who has developed generic Alamofire
request method with decoding & error handling?
Thanks in advance :)