2016-10-06 3 views
1

Код ниже работает нормально Xcode 7.1, но при обновлении до Xcode 8 и swift 3 Я получаю эту ошибку, я искал в Интернете по той же проблеме в stackoverflow, но ни один из них не ответил мой вопрос.Неограниченная ссылка на членский указатель 'при использовании 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 
} 

здесь класс mapTK для получения дополнительной информации:

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

Что такое тип '' mapTk' и mapTk. overviewPolyline'. –

+0

это класс, где я помещал методы для карты, такие как геокод и направление там – sssaaan

+0

@sssaaan - это «обзорПолинии» типа словаря? –

ответ

3

Использование

Dictionary<String, Any> 

, как JSON типа словаря.

ключи JSON должны быть String в любом случае и
AnyObject было изменено на Any в Swift 3.

Edit:

Я рекомендую использовать псевдоним типа для JSON словаря типа

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

Тогда вы можете написать

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

и код парсинга

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

... 

Вы также можете заменить

(... as! NSNumber).doubleValue 

с

... as! Double 
+0

не принимает этого словаря Словарь , предупредите меня, чтобы положить; после String – sssaaan

+0

Я думаю, что для этого требуется a() после этого, таким образом работал – sssaaan

+0

Я обновил ответ несколькими предложениями. – vadian