2016-10-06 4 views
1

Der folgende Code funktioniert gut in Xcode 7.1, aber wenn ich auf Xcode 8 und swift 3 aktualisieren, bekomme ich diesen Fehler, ich hatte im Internet für das gleiche Problem in stackoverflow gesucht, aber keiner von ihnen zu beantworten meine Frage.Mehrdeutiger Verweis auf Mitglied 'tiefgestellt' bei der Verwendung von Google Maps Route

func drawRoute() { 


    clearRoute() 
    // self.routePolyline = nil 
    // self.routePolyline.map = nil 


    let route = mapTk.overviewPolyline!["points"] as String //error here 

    //var overViewPolyLine = routes![0]["overview_polyline"]["points"].string 

    let path: GMSPath = GMSPath(fromEncodedPath: route) 
    routePolyline = GMSPolyline(path: path) 
    routePolyline.map = viewMap 
} 

hier ist die Klasse MapTk für weitere Informationen:

import Foundation 


import UIKit 
import CoreLocation 
import MapKit 

///This Class is designed for the detail methods that contact google maps server like GeoCode, GetDirection and Calculate distance and time 
class MapTK: NSObject { 
    let baseURLGeocode = "https://maps.googleapis.com/maps/api/geocode/json?" 

    var lookupAddressResults: Dictionary<NSObject, AnyObject>! 

    var fetchedFormattedAddress: String! 

    var fetchedAddressLongitude: Double! 

    var fetchedAddressLatitude: Double! 


    let baseURLDirections = "https://maps.googleapis.com/maps/api/directions/json?" 

    var selectedRoute: Dictionary<NSObject, AnyObject>! 

    var overviewPolyline: Dictionary<NSObject, AnyObject>! 

    var originCoordinate: CLLocationCoordinate2D! 

    var destinationCoordinate: CLLocationCoordinate2D! 

    var originAddress: String! 

    var destinationAddress: String! 

    var totalDistanceInMeters: UInt = 0 

    var totalDistance: String! 

    var totalDurationInSeconds: UInt = 0 

    var totalDuration: String! 



    /* private let errorDictionary = ["NOT_FOUND" : "At least one of the locations specified in the request's origin, destination, or waypoints could not be geocoded", 
    "ZERO_RESULTS":"No route could be found between the origin and destination", 
    "MAX_WAYPOINTS_EXCEEDED":"Too many waypointss were provided in the request The maximum allowed waypoints is 8, plus the origin, and destination", 
    "INVALID_REQUEST":"The provided request was invalid. Common causes of this status include an invalid parameter or parameter value", 
    "OVER_QUERY_LIMIT":"Service has received too many requests from your application within the allowed time period", 
    "REQUEST_DENIED":"Service denied use of the directions service by your application", 
    "UNKNOWN_ERROR":"Directions request could not be processed due to a server error. Please try again"] 

    */ 

    override init() { 
     super.init() 
    } 

     ///the geocodeAddress is getting information from googlemaps with JSON it receive the geocode information 
    func geocodeAddress(address: String!, withCompletionHandler completionHandler: @escaping ((_: String, _: Bool) -> Void)) { 
     if let lookupAddress = address { 
      var geocodeURLString = baseURLGeocode + "address=" + lookupAddress 
      //geocodeURLString = geocodeURLString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())! 






      let geocodeURL = NSURL(string: geocodeURLString) 

      // dispatch_Dispatch.Queue.mainasync(dispatch_get_main_queue(), {() -> Void in 
      DispatchQueue.main.async { 

      let geocodingResultsData = NSData(contentsOf: geocodeURL! as URL) 

       // let error: NSError? 

       do 
       { 
       let dictionary = try JSONSerialization.jsonObject(with: geocodingResultsData! as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary 


       // try NSJSONSerialization.JSONObjectWithData(directionsData!, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary 
       /* 
       if (error != nil) { 
        print(error) 
        completionHandler(status: "", success: false) 
       } 

*/ 
//    else { 
        // Get the response status. 
        let status = dictionary?["status"]as! String 
       // let status = dictionary["status"] as! [AnyObject] 



        if status == "OK" { 
         let allResults = dictionary?["results"] as! Array<Dictionary<NSObject, AnyObject>> 
         self.lookupAddressResults = allResults[0] 

         // Keep the most important values. 
         self.fetchedFormattedAddress = self.lookupAddressResults["formatted_address"]? as? String 
         let geometry = self.lookupAddressResults["geometry"] as! Dictionary<NSObject, AnyObject> 
         self.fetchedAddressLongitude = ((geometry["location"] as! Dictionary<NSObject, AnyObject>)["lng"] as! NSNumber).doubleValue 
         self.fetchedAddressLatitude = ((geometry["location"] as! Dictionary<NSObject, AnyObject>)["lat"] as! NSNumber).doubleValue 

         completionHandler(status, true) 
        } 
        else { 
         completionHandler(status, false) 
        } 
       } catch let error as NSError { 

       print(error) 
       } 
      } 
     } 
     else { 
      completionHandler("No valid address.", false) 
     } 
    } 


    ///getDirection method is using JSON to receive waypoints for making route for drawing polyline, as its name suggests it get the direciton inforamtion, first it send lat and lng the receive a dictionary and that dictionary give all the infrmation need to draw route like waypoints 

    func getDirections(origin: String!, destination: String!, waypoints: Array<String>!, travelMode: TravelModes!, completionHandler: @escaping ((_ status: String, _ success: Bool) -> Void)) { 
     if let originLocation = origin { 
      if let destinationLocation = destination { 
       var directionsURLString = baseURLDirections + "origin=" + originLocation + "&destination=" + destinationLocation //+ "&key=AIzaSyDsDqj0EMYZ-C4lGF3tmbntZtzurLl6_J4" 



       if let routeWaypoints = waypoints { 
        directionsURLString += "&waypoints=optimize:true" 

        for waypoint in routeWaypoints { 
         directionsURLString += "|" + waypoint 
        } 
       } 
       if let _ = travelMode { 
        var travelModeString = "" 

        switch travelMode.rawValue { 
        case TravelModes.walking.rawValue: 
         travelModeString = "walking" 

        case TravelModes.bicycling.rawValue: 
         travelModeString = "bicycling" 

        default: 
         travelModeString = "driving" 
        } 




       directionsURLString += "&mode=" + travelModeString 
      } 


       // directionsURLString = directionsURLString.stringByAddingPercentEncodingWithAllowedCharacters(NSUTF8StringEncoding)! 

       // directionsURLString = directionsURLString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)! 

      // directionsURLString = directionsURLString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())! 



       /// directionsURLString = directionsURLString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)! 

       directionsURLString = directionsURLString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)! 


//let encodedHost = unencodedHost.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) 

       //var url = NSURL(urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())) 
       //let savePath = (documentDirectory as NSString).stringByAppendingPathComponent("mergeVideo-\(date).mov") 

       let directionsURL = NSURL(string: directionsURLString) 

       // DispatchQueue.main.asynchronously(execute: {() -> Void in 

        DispatchQueue.main.async { 
        let directionsData = NSData(contentsOf: directionsURL! as URL) 

        // var error: NSError? 

        do { 
let dictionary = try JSONSerialization.jsonObject(with: directionsData! as Data, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary 


         /* 
         if (error != nil) { 
         print(error) 
         completionHandler(status: "", success: false) 
        } 
*/ 
        // else { 
         let status = dictionary?["status"] as! String 

         if status == "OK" { 
          self.selectedRoute = (dictionary?["routes"] as! Array<Dictionary<NSObject, AnyObject>>)[0] 
          self.overviewPolyline = self.selectedRoute["overview_polyline"] as! Dictionary<NSObject, AnyObject> 

          let legs = self.selectedRoute["legs"] as! Array<Dictionary<NSObject, AnyObject>> 

          let startLocationDictionary = legs[0]["start_location"] as! Dictionary<NSObject, AnyObject> 
          self.originCoordinate = CLLocationCoordinate2DMake(startLocationDictionary["lat"] as! Double, startLocationDictionary["lng"] as! Double) 

          let endLocationDictionary = legs[legs.count - 1]["end_location"]as! Dictionary<NSObject, AnyObject> 
          self.destinationCoordinate = CLLocationCoordinate2DMake(endLocationDictionary["lat"] as! Double, endLocationDictionary["lng"] as! Double) 

          self.originAddress = legs[0]["start_address"] as! String 
          self.destinationAddress = legs[legs.count - 1]["end_address"] as! String 

          self.calculateTotalDistanceAndDuration() 

          completionHandler(status, true) 

         } 
         else { 
          completionHandler(status, false) 
         } 



        } catch let error as NSError { 

         print(error) 
        } 

        } 
        } 



      else { 
       completionHandler("Destination is nil.", false) 
      } 
     } 

     else { 
      completionHandler("Origin is nil", false) 
     } 

    } 


/// this method below is for the calculation of Distance adn Duration of each location for travel 

    func calculateTotalDistanceAndDuration() { 
     let legs = self.selectedRoute["legs"] as! Array<NSDictionary> 

     totalDistanceInMeters = 0 
     totalDurationInSeconds = 0 

     for leg in legs { 
      totalDistanceInMeters += (leg["distance"] as! Dictionary<NSObject, AnyObject>)["value"] as! UInt 
      totalDurationInSeconds += (leg["duration"]as! Dictionary<NSObject, AnyObject>)["value"] as! UInt 
     } 


     let distanceInKilometers: Double = Double(totalDistanceInMeters/1000) 
     totalDistance = "Total Distance: \(distanceInKilometers) Km" 


     let mins = totalDurationInSeconds/60 
     let hours = mins/60 
     let days = hours/24 
     let remainingHours = hours % 24 
     let remainingMins = mins % 60 
     let remainingSecs = totalDurationInSeconds % 60 

     totalDuration = "Duration: \(days) d, \(remainingHours) h, \(remainingMins) mins, \(remainingSecs) secs" 
    } 






} 
+0

Was ist die Art von 'mapTk' und' MapTk ersetzen kann. ÜberblickPolyline'. –

+0

es ist eine Klasse, wo ich die Methoden für Karte wie Geocode und Richtung dort setzen – sssaaan

+0

@sssaaan ist 'overviewPolyline' Typ des Wörterbuchs? –

Antwort

3

Verwenden

Dictionary<String, Any> 

als JSON Wörterbuchtyp.

JSON Schlüssel benötigt String sowieso und
AnyObject wurde Any in Swift 3.

bearbeiten geändert werden:

Ich empfehle zu verwenden, um eine Art Alias ​​für das JSON Wörterbuchtyp

typealias JSONObject = [String:Any] // synonym of Dictionary<String, Any> 

Dann können Sie

schreiben
var lookupAddressResults: JSONObject! 
... 
var selectedRoute: JSONObject! 
var overviewPolyline: JSONObject! 

und die Parsing-Code

... 
    if status == "OK" { 
     let allResults = dictionary?["results"] as! Array<JSONObject> 
     self.lookupAddressResults = allResults[0] 

     // Keep the most important values. 
     self.fetchedFormattedAddress = self.lookupAddressResults["formatted_address"] as? String 
     let geometry = self.lookupAddressResults["geometry"] as! JSONObject 
     self.fetchedAddressLongitude = ((geometry["location"] as! JSONObject)["lng"] as! NSNumber).doubleValue 
     self.fetchedAddressLatitude = ((geometry["location"] as! JSONObject)["lat"] as! NSNumber).doubleValue 

     completionHandler(status, true) 
     } 

... 

Sie auch

(... as! NSNumber).doubleValue 

mit

... as! Double 
+0

es akzeptiert nicht diesen Typ Wörterbuch , warnt mich zu setzen; nach String – sssaaan

+0

Ich denke, es erfordert a() nach diesem, so funktioniert – sssaaan

+0

Ich aktualisierte die Antwort mit ein paar Anregungen. – vadian

Verwandte Themen