Search code examples
swiftalamofiregeneric-programmingdecodable

Generic function with Alamofire


I work with iOS app that use Alamofire, I want to write a generic function(s) which used to send and retrieve data from server to a decodable objects, my function was as below :

func pop <T : Codable>  (_ Url: inout String, _ popedList: inout [T]) {
    let url = URL(string:Url)
    Alamofire.request(url!, method: .post).responseJSON { response in
        let result = response.data
        do {
            let data = try JSONDecoder().decode(popedList, from: result!)// get error here
            print(data[0])

            let jsonEncoder = JSONEncoder()
            let jsonData = try! jsonEncoder.encode(data[0])
            let jsonString = String(data: jsonData, encoding: .utf8)
            print("jsonString: \(String(describing: jsonString))")

        } catch let e as NSError {
            print("error : \(e)")
        }
    }
} 

and a function to send an object to server as below:

func push <T : Codable>  (_ Url: inout String, _ pushObject: inout T) {
    let jsonData = try! JSONEncoder().encode(pushObject)
    let jsonString = String(data: jsonData, encoding: .utf8)
    print("jsonString: \(String(describing: jsonString))")

    let url = URL(string:Url)

    Alamofire.request(url!,
                      method: .post,
                      parameters:jsonString)//it's need to creat a Dictionary instate of String
        .validate(statusCode: 200..<300)
        .validate(contentType: ["application/json"])
        .response { response in
            // response handling code
             let result = response.data
            print(response.data)
    }
}

I get an error in first function,

"Cannot invoke 'decode' with an argument list of type '([T], from: Data)'"

and

"Escaping closures can only capture inout parameters explicitly by value"

What is the best way to write these to function as generic?


Solution

  • After a few searches and trying to edit my functions I capable to rewrite my two functions in such away that I get what I need:

     func pop<T: Decodable>(from: URL, decodable: T.Type, completion:@escaping (_ details: [T]) -> Void)
                {
           Alamofire.request(from, method: .post).responseJSON { response in
                    let result_ = response.data
                    do {
                        let data = try JSONDecoder().decode([T].self, from: result_!)
                        //let data = try JSONDecoder().decode(decodable, from: result_!)// get error here
                        //print(data[0])
                        print("data[0] : \(data[0])")
                        completion(data)
                    } catch let e as NSError {
                        print("error : \(e)")
                    }
                }
            }
    
        func push <T : Codable>  (_ Url:  String, _ pushObject:  T)
            {
                let jsonData = try! JSONEncoder().encode(pushObject)
                let jsonString = String(data: jsonData, encoding: .utf8)
                print("jsonString: \(String(describing: jsonString))")
    
                let url = URL(string:Url)
    
                Alamofire.request(url!,
                                  method: .post,
                                  parameters:convertToDictionary(text: jsonString!))//it's need to creat a Dictionary instate of String
                    .validate(statusCode: 200..<300)
                    .validate(contentType: ["application/json"])
                    .response { response in
                        // response handling code
                        print(response.data!)
                        if let jsonData = response.data {
                            let jsonString = String(data: jsonData, encoding: .utf8)
                            print("response.data: \(String(describing: jsonString))")
                        }
                }
            }
    
            func convertToDictionary(text: String) -> [String: Any]? {
                if let data = text.data(using: .utf8) {
                    do {
                        return try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any]
                    } catch {
                        print(error.localizedDescription)
                    }
                }
                return nil
            }