2017-11-28 2 views
0

Mit Swift4, iOS11.1, Xcode9.1,Fehlende Daten mit URLSession und JSONDecode in Swift4

Die folgende parseData Methode funktioniert fast. Alles scheint gut zu funktionieren (und ein korrekter JSON-Datensatz wird von dieser URLSession und JSONDecode abgerufen).

Was mich jedoch wirklich überrascht, ist die Tatsache, dass ein normaler Browser verschiedene JSON-Daten anzeigt (d. H. 20x wird so viel abgerufen wie im Vergleich zu dieser iOS-URLSession-Methode). Warum das ??

Im folgenden Code finden Sie zwei Druckanweisungen. Die erste zeigt die URLRequest-Zeichenfolge (einschließlich aller Abfrage- und Typparameter). Die zweite gibt die Anzahl der abgerufenen JSON-Datensätze aus.

Wenn Sie einen Browser verwenden und den JSON mit genau der gleichen URLRequest-Zeichenfolge abrufen, beträgt die Anzahl der Datensätze 20 Sätze. Mit der URLSession ist es nur 1 Satz

Warum dieser Unterschied in JSON Datenlänge geliefert ?????????? Hier

ist PRINT_LOG 1:

https://maps.googleapis.com/maps/api/place/textsearch/json?query=Cham,%20Langackerstrasse&type=bus_station&key=AIzaSyDYtkKiJRuJ9tjkeOtEAuEtTLp5a0XR1M0 

(API key no longer valid - after having found the solution, I did change the API-key for security reasons. The Question and its Answer are still of value tough). 

Hier ist PRINT_LOG 2:

count = 1 

Hier ist mein Code:

func parseData(queryString: String) { 

    // nested function 
    func createURLWithComponents() -> URL? { 
     let urlComponents = NSURLComponents() 
     urlComponents.scheme = "https"; 
     urlComponents.host = "maps.googleapis.com"; 
     urlComponents.path = "/maps/api/place/textsearch/json"; 
     // add params 
     urlComponents.queryItems = [ 
      URLQueryItem(name: "query", value: "Cham, Langackerstrasse"), 
      URLQueryItem(name: "type", value: "bus_station"), 
      URLQueryItem(name: "key", value: AppConstants.GOOGLE_MAPS_DIRECTIONS_API_KEY) 
     ] 

     return urlComponents.url 
    } 

    let myUrl = createURLWithComponents() 
    var myRequest = URLRequest(url: myUrl!) 
    myRequest.httpMethod = "GET" 
    myRequest.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type") 

    let myConfiguration = URLSessionConfiguration.default 
    let session = URLSession(configuration: myConfiguration, delegate: nil, delegateQueue: OperationQueue.main) 

    // Until here everything all right !!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
    // i.e. the following print is correct !!!!!!!!!!!!!!!!!!!!!!!!! 
    // (and when this print is copied to a Browser then the data fetched has 20 JSON-entries...) 
    // PRINT_LOG 1 
    print(myRequest.description) 

    let myTask = session.dataTask(with: myRequest) { (data, response, error) in 

     if (error != nil) { 
      print("Error1 fetching JSON data") 
     } 
     else { 
      do { 
       //Decode retrived data with JSONDecoder and assing type of Station object 
       let stationData = try JSONDecoder().decode(Station.self, from: data!) 

       // Here is the puzzling thing to happen !!!!!!!!!!!!!!!!!!!!!! 
       // i.e. the following print reveals count = 1 !!!!!!!!!!!!!!!!! 
       // ??? Why not 20 as with the Browser ???????????????????? 
       // PRINT_LOG 2 
       print("count = " + "\(String(describing: stationData.results.count))") 
      } 
      catch let error { 
       print(error) 
      } 
     } 
    } 
    myTask.resume() 
} 

Der Vollständigkeit halber ist hier die passende Struct:

struct Station: Codable { 

    let htmlAttributions: [String] 
    let nextPageToken: String? 
    let results: [Result] 
    let status: String 

    struct Result: Codable { 
     let formattedAddress: String 
     let geometry: Geometry 
     let icon: String 
     let id: String 
     let name: String 
     let photos: [Photo]? 
     let placeID: String 
     let rating: Double? 
     let reference: String 
     let types: [String] 

     struct Geometry: Codable { 
      let location: Coordinates 
      let viewport: Viewport 

      struct Coordinates: Codable { 
       let lat: Double 
       let lng: Double 
       init(from decoder: Decoder) throws { 
        let values = try decoder.container(keyedBy: CodingKeys.self) 
        lat = try values.decode(Double.self, forKey: .lat) 
        lng = try values.decode(Double.self, forKey: .lng) 
       } 
       enum CodingKeys : String, CodingKey { 
        case lat 
        case lng 
       } 
      } 

      struct Viewport: Codable { 
       let northeast: Coordinates 
       let southwest: Coordinates 

       enum CodingKeys : String, CodingKey { 
        case northeast 
        case southwest 
       } 
      } 

      enum CodingKeys : String, CodingKey { 
       case location 
       case viewport 
      } 
     } 

     struct Photo: Codable { 

      let height: Int 
      let htmlAttributions: [String] 
      let photoReference: String? 
      let width: Int 
      enum CodingKeys : String, CodingKey { 
       case height 
       case htmlAttributions = "html_attributions" 
       case photoReference = "photo_reference" 
       case width 
      } 
     } 

     enum CodingKeys : String, CodingKey { 
      case formattedAddress = "formatted_address" 
      case geometry 
      case icon 
      case id 
      case name 
      case photos 
      case placeID = "place_id" 
      case rating 
      case reference 
      case types 
     } 
    } 

    enum CodingKeys : String, CodingKey { 
     case htmlAttributions = "html_attributions" 
     case nextPageToken = "next_page_token" 
     case results 
     case status 
    } 
} 

Danke für jede Hilfe zu diesem Thema.

+0

Ich bekomme 'count = 20' mit Ihrem Code. Möglicherweise müssen Sie herausfinden, was anders ist, wenn Sie "count = 1" erhalten, nicht nur aus Ihrem Code. – OOPer

+0

Genau dieser Unterschied ist meine Frage :)? Keine Ahnung, ich lande mit count = 1 !! Was ist Ihr Info.plist sagen über Zugriffsrechte (i.e.mine sagt: \t ' \t \t NSAllowsArbitraryLoads \t \t \t \t NSExceptionDomains \t \t maps.googleapis. com NSExceptionRequiresForwardSecrecy \t \t \t 'Was sonst könnte dieses Problem verursachen? Einige Spracheinstellungen (d. H. Lokalisierung)? Oder was noch? Jede Hilfe wird geschätzt! – iKK

Antwort

0

Es gefunden !!!

Es war die fehlende Lokalisierung von Info.plist! (d. h. ich habe den App-Formular-XCode ausgeführt, bei dem die Sprache unter Start -> Optionen -> Anwendungssprache auf Deutsch eingestellt ist). Meine Info.plist wurde nur teilweise lokalisiert (d. H. Meine Datei InfoPlist.strings hatte nur ein paar Einträge - aber keine vollständige Übersetzung). Und diese fehlende Übersetzung führt zu diesem Problem !!!!

Laufen in reinem Englisch funktioniert gut und ich bekomme 20 Einträge wie erwartet.