Как передать encodable или decodable в качестве параметра в swift 4?

Я изучаю JSONParsing. Я следил за учебниками и получил следующее:

    guard let url = URL(string: "http://localhost/test-api/public/api/register") else { return }

    var request  = URLRequest(url: url)

    request.httpMethod = "POST"

    let newUser = User.init(name: self.collectionTF[0].text, email: self.collectionTF[1].text, password: self.collectionTF[2].text)

    do {

        let jsonBody = try JSONEncoder().encode(newUser)

        request.httpBody = jsonBody

    } catch { }

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

        guard let data = data else { return }

        do {

            let json = try JSONSerialization.jsonObject(with: data) as? [String:Any]

            print(json!)

            DispatchQueue.main.async {

            if json!["status"] as! Int == 200
            {
                GeneralHelper.shared.keepLoggedIn()

                NavigationHelper.shared.moveToHome(fromVC: self)
            }

            }

        } catch { print(error.localizedDescription)}

        }.resume()

Хорошо, вот что я сделал для регистрации. Теперь я хочу создать помощника, который будет делать то же самое с @escaping, поскольку мне всем нам нужен взамен проанализированный JSON.

Итак, я передаю endPoint как String, а затем пытаюсь передать этого нового пользователя, который является Encodable, он может быть и Decodable в будущем, но он выдает ошибку Cannot invoke 'encode' with an argument list of type '(Codable)'. Кто-нибудь может помочь? И лучше ли так, вызывая эту функцию несколько раз, когда дело касается JSONParsing?

Обновлено: - Итак, теперь я использую networkRequestfunction, и вот что я сделал.

 let newData = User.init(name: "Rob", email: "abc@gmail.com", password: "12345678")

ApiHelper.sharedInstance.networkRequest_Post(urlString: "register", header: nil, encodingData: newData) { (response: User, urlRes, error) in
        <#code#> }

Теперь это дает мне эту ошибку: Cannot convert value of type '(User, _, _) -> ()' to expected argument type '(_?, HTTPURLResponse?, Error?) -> ()'. Любая помощь?

Я создал классы-оболочки. Попробуйте github.com/PrashantKT/AlamofireHelperLayer.

Prashant Tukadiya 26.10.2018 08:56
4
1
5 813
2

Ответы 2

Вы можете использовать Дженерики следующим образом ...

func requestWith<T>(method: HTTPMethod, action: String,  params: Parameters?, for type: T.Type, success: @escaping (AnyObject) -> Void, failure: @escaping (AnyObject) -> Void) where T: Codable {


//do your stuff..your logic goes here..see below example

     guard let serverData = response.data else {
           return
        }

   do {
     let decoder = JSONDecoder()
     let responseData = try decoder.decode(type, from: serverData)
       success(responseData as AnyObject)
    } catch {
      print("Error = \(error.localizedDescription)")
       failure(error.localizedDescription as AnyObject)
   }

}

Codable - это супер протокол Decodable & Encodable ... просто попробуйте.

Mahendra 26.10.2018 08:30

Неуказанный AnyObject не подходит для универсальной функции. Лучше func requestWith<T>(method: HTTPMethod, action: String, params: Parameters?, success: @escaping (T) -> Void, failure: @escaping (Error) -> Void) where T: Codable {

vadian 26.10.2018 08:31

Я знаю, здесь вы использовали JSONDecoder, поэтому я спрашиваю, что мне делать, если я хочу encode?

Rob13 26.10.2018 08:31

@vadian, это просто пример :)

Mahendra 26.10.2018 08:53

Да, но, пожалуйста, предложите лучшие примеры тем, кто копирует и вставляет код вместе.

vadian 26.10.2018 08:58

@vadian Можете ли вы показать мне пример или что-нибудь еще, где используются как JSONEncoder, так и Decoder? Или любой учебник, которому я могу следовать?

Rob13 26.10.2018 09:12

Отличный пример! Думаю, это меня просто зацепило дженериками ... 😄

LinusGeffarth 08.04.2019 22:13

Я использовал ту же функциональность в своем проекте

Надеюсь, приведенный ниже код поможет

    func networkRequest_Post<T: Decodable, Q: Encodable>(urlString: String,header:[String:String]?,encodingData: Q,completion: @escaping (T?, HTTPURLResponse?, Error?) -> ()) {

    guard let url = URL(string: urlString) else { return }
    let config = URLSessionConfiguration.default
    config.timeoutIntervalForRequest = 300.0
    config.timeoutIntervalForResource = 300.0
    if header != nil{
        config.httpAdditionalHeaders = header
    }
    let session = URLSession(configuration: config)
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    do {
        let jsonBody = try JSONEncoder().encode(encodingData)
        request.httpBody = jsonBody
    } catch {}
    let task = session.dataTask(with: request) { (data,response, err) in

        if let response = response {
            print(response)
        }
        if let err = err {
            print("Failed to fetch data:", err.localizedDescription, "Error Description\(err)")
            return
        }
        guard let data = data else { return }
        do {
            print(String(data: data, encoding: String.Encoding.utf8) as Any)
            let dataReceived = try JSONDecoder().decode(T.self, from: data)
                completion(dataReceived,response as? HTTPURLResponse,err)
        } catch let jsonErr {
            print("Failed to serialize json:", jsonErr, jsonErr.localizedDescription)
            completion( nil,response as? HTTPURLResponse,jsonErr)
        }
    }
    task.resume()
}

Использовать -

         let newdata = User(name: "Abhi", email: "jhjhj@jhj.co", password: "123hguhj")
    networkRequest_Post(urlString: "YOUR_URL", header: nil, encodingData: newdata) { (RESPONSE_DATA:User?, URL_RESPONSE, ERROR) in
        // Do your network work here
    }

    struct User : Codable {
      var name: String?
      var email: String?
      var password: String?
    }

Хорошо, не могли бы вы показать мне такую ​​функцию, как вызов функции с декодируемым и кодируемым, извините, но мне все не так ясно, когда дело доходит до дженериков, я очень новичок в этом. Небольшой справочник мне поможет.

Rob13 26.10.2018 09:54

Нужен ли мне заголовок?

Rob13 26.10.2018 11:52

У меня было требование к заголовку, поэтому я добавил его. Я сделал это опцией и обновил свой код

Abhinav Jha 26.10.2018 11:57

Я обновил свой вопрос, пожалуйста, проверьте часть редактирования, это вызывает у меня головную боль. Вы знаете, что здесь не так?

Rob13 26.10.2018 17:08

Ожидаемый тип является необязательным, и вы передаете необязательное значение. Передайте значение, как показано ниже. ApiHelper.sharedInstance.networkRequest_Post (urlString: "register", header: nil, encodingData: newData) {(response: User ?, urlRes ?, error ?) в

Abhinav Jha 26.10.2018 17:21

Я обновил свой ответ и протестировал его в xcode, пожалуйста, проверьте мои ответы

Abhinav Jha 26.10.2018 17:30

Мой struct User был типа Encodable. я должен поменять его на Codable. Вот почему это не сработало.

Rob13 26.10.2018 17:39

Да, сделайте его кодируемым и дайте мне знать, сработало ли это

Abhinav Jha 26.10.2018 17:40

Позвольте нам продолжить обсуждение в чате.

Rob13 26.10.2018 17:42

Другие вопросы по теме