2016-10-06 3 views
1

以下のコードはXcode 7.1で正常に動作しますが、Xcode 8swift 3にアップグレードすると、インターネットでstackoverflowで同じ問題が検索されましたが、私の質問。Googleマップルートを使用している場合、メンバー 'subscript'へのあいまいな参照

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

(... as! NSNumber).doubleValue 

を置き換えることができます。 overviewPolyline'を参照してください。 –

+0

それは私が地理コードと方向のようなマップのメソッドを置くクラスです – sssaaan

+0

@sssaaanは 'overviewPolyline'タイプの辞書ですか? –

答えて

3

使用JSON辞書の種類として

Dictionary<String, Any> 

:ここ

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です。

JSONのキーはとにかくStringであることが要求されると
AnyObjectは、スウィフトにAnyに変更された3

編集:私は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) 
     } 

... 

また `mapTk`と` mapTkの種類は何

... as! Double 
+0

このタイプは受け入れません。辞書、 String – sssaaan

+0

の後に私はその後にa()が必要だと思います。その方法では – sssaaan

+0

私はいくつかの提案で答えを更新しました。 – vadian

関連する問題