可选类型字符串?没有打开

时间:2017-04-14 22:58:41

标签: json swift

我的网页服务器上有一个PHP页面,它与名为grabmapinfo.php的mysql数据库进行交互

页面的输出为[{"companyname":"Brunos Burgers","companyphone":"7745632382","companytown":"858 Western Ave, Lynn, MA 01905"}]

现在我有了这个Swift代码,我希望从数据库中获取信息,将地址地理编码为纬度和经度,在地图上绘制注释,更改注释图像和标题,并创建一个半径为圆的5,销钉位于中心。

let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.

        self.locationManager.delegate = self

        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest

        self.locationManager.requestWhenInUseAuthorization()

        self.locationManager.startUpdatingLocation()

        self.buyerMapView1.showsUserLocation = true

        let url = NSURL(string: "https://alanr917.000webhostapp.com/grabmapinfo.php")

        var request = URLRequest(url:url! as URL)

        URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (data:Data?, response:URLResponse?, error:Error?) -> Void in

            if error != nil {
                // Display an alert message

                print(error)

                return
            }

            do {

                if let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [[String:AnyObject]] {
                    for item in json {
                        // Get company info from DB
                        let companyname = item["companyname"] as? String
                        let companyphone = item["companyphone"] as? String
                        let companytown = item["companytown"] as? String

                        print("Company : \(companyname)")
                        print("Phone : \(companyphone)")
                        print("Address : \(companytown)")

                        let address = companytown
                        let geocoder = CLGeocoder()
                        geocoder.geocodeAddressString(address, completionHandler: {
                            (placemarks: [AnyObject]!, error: NSError!) -> Void in
                            if let placemark = placemarks?[0] as? CLPlacemark {
                                let pa = MKPointAnnotation()
                                pa.coordinate = placemark.location.coordinate
                                pa.title = companyname
                                pa.imageName = #imageLiteral(resourceName: "growerAnnotation")
                                self.buyerMapView1.addAnnotation(pa)

                                let center = annotation.coordinate
                                let circle = MKCircle(center: center, radius: 5) // change the 5 later to however many miles the grower purchased
                                self.buyerMapView1.add(circle)
                            }
                        })
                    }
                }
            } catch  {
                print(error)
            }
        })
    }

但我得到一个错误,说明可选类型字符串?没有解开,它出错并且不会构建。

有谁知道我哪里出错了?谢谢!

2 个答案:

答案 0 :(得分:1)

companyTown被声明为可选字符串,geocodeAddressString方法接受一个字符串。您需要在调用之前解开该选项。

if let addressUnwrapped = address {
    geocoder.geocodeAddressString(addressUnwrapped, completionHandler: {
                        (placemarks: [AnyObject]!, error: NSError!) -> Void in
                        ...
    })
}

答案 1 :(得分:0)

请通过代码查看注释,以获取有关我在代码中发现的问题的更详细说明:

import UIKit
import CoreLocation
import MapKit

class ViewController: UIViewController, CLLocationManagerDelegate {

    @IBOutlet weak var buyerMapView1: MKMapView!

    let locationManager = CLLocationManager()

    override func viewDidLoad() {
        super.viewDidLoad()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
        buyerMapView1.showsUserLocation = true
        // first unwrap your url
        guard let url = URL(string: "https://alanr917.000webhostapp.com/grabmapinfo.php") else { return }
        print("url:",url)
        // no need to create a request. just a url is fine and you don't need to specify the parameters type. Let the compiler infer it.
        URLSession.shared.dataTask(with: url) { data, response, error in
            // unwrap your data and make sure there is no error
            guard let data = data, error == nil else {
                print(error ?? "nil")
                return
            }
            // you should update the UI from the main queue
            DispatchQueue.main.async {
                print("data:", data)
                do {
                    if let array = try JSONSerialization.jsonObject(with: data) as? [[String: Any]] {
                        for dict in array {
                            // make sure you unwrap your dictionary strings
                            let companyname = dict["companyname"] as? String ?? ""
                            let companyphone = dict["companyphone"] as? String ?? ""
                            let companytown = dict["companytown"] as? String ?? ""
                            print("Company:", companyname)
                            print("Phone:", companyphone)
                            print("Address:", companytown)
                            let address = companytown
                            let geocoder = CLGeocoder()
                            // again let the compiler infer the types   vvv       vvv
                            geocoder.geocodeAddressString(address) { placemarks, error in
                                if let placemark = placemarks?.first,
                                    let coordinate = placemark.location?.coordinate {
                                    let pa = MKPointAnnotation()
                                    pa.coordinate = coordinate
                                    pa.title = companyname
                                    self.buyerMapView1.addAnnotation(pa)
                                    let center = pa.coordinate   // where does this coordinate come from??
                                    let circle = MKCircle(center: center, radius: 5)
                                    self.buyerMapView1.add(circle)
                                }
                            }
                        }
                    }
                } catch {
                    print(error)
                }
            }
        // you forgot to call resume to start your data task
        }.resume()
    }
}