2017-09-17 12 views
1

Ich versuche, eine generische Netzwerkfunktion zu erstellen Ich suche einen API-Handler, der JSON aus dem Netzwerk herunterladen und Theme in Swift-Strukturen konvertieren wird, die dem Decodable-Protokoll entsprechen. Derzeit bin ich mit expliziten Typen:Networking Call mit generischem Dekodierungstyp

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() 
} 

ich eine generische Funktion erstellen bin der Hoffnung, wo ich jeden Datentyp angeben können, welche das Datenobjekt zu Decodable und haben bestätigt, in dem Abschluss-Handler zurückgegeben. Etwas in der Form von:

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() 
} 

Allerdings kann ich nicht scheinen, um die Funktionsparameter richtig zu bekommen. Ich habe nicht viel Erfahrung mit Generika zu arbeiten. Jede mögliche Hilfe würde

Antwort

1

erkannt werden, können Sie die Erklärung des decode Methode der JSONDecoder imitieren:

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

Anwendung der Rüttler oben, um Ihren Code, sollte die Definition so etwas wie dieses:

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() 
} 

Oder Sie können es auf diese Weise schreiben:

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

Großartig swer! Lief wie am Schnürchen –