2017-09-17 4 views
1

Je tente de créer une fonction de mise en réseau générique Je cherche à créer un gestionnaire d'API qui téléchargera JSON à partir du réseau et convertira le thème en structures Swift conformes au protocole Decodable. Actuellement, je suis en utilisant les types explicites:Appel de réseau avec le type de décodage générique

struct MyObject : Decodable { 
    let id : Int 
    let name : String 
} 

static fileprivate func makeNetworkRequest(url: URL, completionHandler: @escaping(_ error: Error?, _ myObject: MyObject?) ->()) { 
    URLSession.shared.dataTask(with: url) { (data, response, error) in 
     // handle error 
     do { 
      let myNewObject = try JSONDecoder().decode(MyObject.self, from: data!) 
      completionHandler(nil, myNewObject) 
     } 
     catch let error { 
      completionHandler(error, nil) 
      return 
     } 
    }.resume() 
} 

J'espère créer une fonction générique où je peux spécifier un type de données qui confirme Decodable et ont l'objet de données renvoyées dans le gestionnaire d'achèvement. Quelque chose du genre:

static fileprivate func makeNetworkRequest<T>(url: URL, type: <<<Decodable Type>>>, completionHandler: @escaping(_ error: Error?, _ myObject: <<<Deocable Object>>>?) ->()) { 
    URLSession.shared.dataTask(with: url) { (data, response, error) in 
     // handle error 
     do { 
      let myNewObject = try JSONDecoder().decode(<<<Decodable Type>>>.self, from: data!) 
      completionHandler(nil, myNewObject) 
     } 
     catch let error { 
      completionHandler(error, nil) 
      return 
     } 
    }.resume() 
} 

Cependant, je n'arrive pas à obtenir les paramètres de fonction corrects. Je n'ai pas beaucoup d'expérience de travail avec les génériques. Toute aide serait appréciée

Répondre

1

Vous pouvez imiter la déclaration de la méthode decode de JSONDecoder:

open func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : Decodable 

application du boniment ci-dessus à votre code, la définition doit être quelque chose comme ceci:

static fileprivate func makeNetworkRequest<T>(url: URL, type: T.Type, completionHandler: @escaping (_ error: Error?, _ myObject: T?) ->()) 
where T: Decodable 
{ 
    URLSession.shared.dataTask(with: url) { (data, response, error) in 
     // handle error 
     do { 
      let myNewObject = try JSONDecoder().decode(T.self, from: data!) 
      completionHandler(nil, myNewObject) 
     } catch let error { 
      completionHandler(error, nil) 
      return 
     } 
    }.resume() 
} 

Ou vous pouvez l'écrire de cette façon:

static fileprivate func makeNetworkRequest<T: Decodable>(url: URL, type: T.Type, completionHandler: @escaping (_ error: Error?, _ myObject: T?) ->()) { 
    URLSession.shared.dataTask(with: url) { (data, response, error) in 
     // handle error 
     do { 
      let myNewObject = try JSONDecoder().decode(T.self, from: data!) 
      completionHandler(nil, myNewObject) 
     } catch let error { 
      completionHandler(error, nil) 
      return 
     } 
    }.resume() 
} 
+0

swer! Travaillé comme un charme –