Home > front end >  How to pass a function parameter to the generic structure in swift
How to pass a function parameter to the generic structure in swift

Time:09-17

I am trying to pass a model/struct as a parameter in function and passing it to another struct/model with generic type here is my code

---> Function

func getAPICallModelDecodable<T:Codable> (url:String,model:T,
                                          success: @escaping (_ responseObject:T?)->Void,
                                          failure: @escaping (_ error:String) -> Void ,
                                          method:HTTPMethod = .get) {
    print(type(of: model))
    AF.request(url,method:method).responseDecodable(of: FetchAPI<T(Want to pass model parameter here)>.self) { respons in
        print(respons)
        switch respons.result {
        case .success(let data):
            if data.flag! {
                success(data.data)
            }
        case .failure(let error):
            failure(error.localizedDescription)
        }
    }
}

---> FetchAPI Struct

struct FetchAPI<T:Codable>:Codable {
    
    var flag: Bool?
    var statusCode: Int?
    var message: String?
    var data: T?
    
    enum CodingKeys: String, CodingKey {
        case flag = "Flag"
        case statusCode = "StatusCode"
        case message = "Message"
        case data = "Data"
    }
}    

Model parameter can be any codable structure

CodePudding user response:

Currently your function getAPICallModelDecodable is defined in such a way that you have to pass in a model of type T. But if I understand it correctly, you only want to pass in (define) the type T.

For this you have to change the function as follows:

func getAPICallModelDecodable<T:Codable> (url: String, type: T.Type,
                                          success: @escaping (_ responseObject:T?)->Void,
                                          failure: @escaping (_ error:String) -> Void ,
                                          method:HTTPMethod = .get) 

In the function body you can use T e.g. simply like this:

AF.request(url,method:method).responseDecodable(of: FetchAPI<T>.self)

The function call would then look like this:

getAPICallModelDecodable(url: ..., type: Model.self, ...)

CodePudding user response:

You don't have to pass the model or the type of the model explicitly, the compiler can deduce that from when you call the method.

So your func declaration should be

func getAPICallModelDecodable<T:Codable>(url:String,
                                         success: @escaping (_ responseObject: T?) -> Void,
                                         failure: @escaping (_ error: String) -> Void ,
                                         method:HTTPMethod = .get) {

and the request call should be

AF.request(url,method:method).responseDecodable(of: FetchAPI<T>.self) 

I don't use Alamofire myself so here is a more complete example using a quick implementation using URLSession and a model Test that conforms to Codable

func makeApiCall<T: Codable>(url: URL,
                             success: @escaping (_ responseObject: T?) -> Void,
                             failure: @escaping (_ error: String) -> Void) {
    let request = URLRequest(url: url)
    URLSession.shared.dataTask(with: request) { (data, response, error) in
        if let error = error {
            failure("\(error)")
        }
        
        if let data = data {
            do {
                let result = try JSONDecoder().decode(FetchAPI<T>.self, from: data)
                success(result.data)
            } catch {
                failure("\(error)")
            }
        } else {
            failure("No error, no data")
        }
    }
    .resume()
}

func success(_ model: Test?) {}
func failure(_ error: String) {}

let url = URL(string: "http://someurl")!
makeApiCall(url: url, success: { success($0) }, failure: { failure($0) })
  • Related