【问题标题】:Swift 2 - Optional Strings Appear upon Automatic LocationSwift 2 - 自动定位时出现可选字符串
【发布时间】:2015-10-11 22:16:51
【问题描述】:

我的应用程序中有一个自动定位功能,但自从我更新到 swift 2 后,我开始获得在显示每个部分的位置详细信息之前出现的“可选字符串”,有什么建议可以解决这个问题吗?

这是它显示的内容:

Optional("Cupertino")
Optional("95014")
Optional("CA")
Optional("United States")
--------------------
*** location: ***
Optional(<+37.33233141,-122.03121860> +/- 5.00m (speed 0.00 mps / course -1.00) @ 10/11/15, 11:05:28 PM British Summer Time)

下面是我的代码

import UIKit
import Foundation
import MapKit
import CoreLocation
import SystemConfiguration
import MobileCoreServices

class GeoLocation: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {

    // GeoLocation IBOutlets Set

    @IBOutlet weak var mapView: MKMapView!
    @IBOutlet weak var myAddressView: UITextField!
    @IBOutlet weak var myLocationVIew: UITextField!

    @IBOutlet weak var BUTTONA: UIButton!

    @IBAction func BrightnessIncrease(sender: AnyObject) {

        UIScreen.mainScreen().brightness = CGFloat(1.0)
    }

    @IBAction func BrightnessDecrease(sender: AnyObject) {

        UIScreen.mainScreen().brightness = CGFloat(0.4)
    }

    var locationManager:CLLocationManager!

    override func viewDidLoad() {
        super.viewDidLoad()

        myAddressView.hidden = true
       myLocationVIew.hidden = true

        locationManager = CLLocationManager()
        locationManager.requestAlwaysAuthorization()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.delegate = self
        locationManager.startUpdatingLocation()

        mapView.showsUserLocation = true
        mapView.delegate = self
        mapView.mapType = MKMapType.Hybrid
        CLLocationManager().requestAlwaysAuthorization()

        self.myAddressView.borderStyle = UITextBorderStyle.RoundedRect

        self.myLocationVIew.borderStyle = UITextBorderStyle.RoundedRect

        // Do any additional setup after loading the view, typically from a nib.
    }

    @IBAction func DATA2(sender: AnyObject) {

        if myAddressView.text != ""
        {
            SECTIONB = myAddressView.text
        }
        else
        {
            performSegueWithIdentifier("Transferfile", sender: sender)

            }
    }

    @IBAction func DATA3(sender: AnyObject) {

        if myLocationVIew.text != ""
        {
            SECTIONC = myLocationVIew.text
        }
        else
        {
            performSegueWithIdentifier("Transferfile", sender: sender)

        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    // Map Display and Region Zoom

    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let regionToZoom = MKCoordinateRegionMake(manager.location!.coordinate, MKCoordinateSpanMake(0.005, 0.005))

        mapView.setRegion(regionToZoom, animated: true)

        myLocationVIew.text = "\(locationManager.location)"

        CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: { (placemarks, error) -> Void in
            if error != nil {
                print("Error: " + error!.localizedDescription)
                return
            }
            if placemarks!.count > 0 {
            let pm = placemarks?[0] 
            self.displayLocationInfo(pm!)

            }
        })
    }

    func displayLocationInfo(placemark: CLPlacemark) {

        // This Section stops updating location constantly.

        //   self.locationManager.stopUpdatingLocation()

        // This Section display address parameters in a column on UILabel
        //            var address = (
        //                (placemark.subThoroughfare),
        //                (placemark.thoroughfare),
        //                (placemark.subLocality),
        //                (placemark.locality),
        //                (placemark.postalCode),
        //                (placemark.administrativeArea),
        //                (placemark.country))

        //          myAddressView.text = "\(address)"


        myAddressView.text = " \(placemark.subThoroughfare) \(placemark.thoroughfare) \r \(placemark.subLocality) \r \(placemark.locality) \(placemark.administrativeArea) \(placemark.postalCode) \r \(placemark.country)"

        print("-----START UPDATE-----")
        print(placemark.subThoroughfare)
        print(placemark.thoroughfare)
        print(placemark.locality)
        print(placemark.postalCode)
        print(placemark.administrativeArea)
        print(placemark.country)
        print("--------------------")
        print("*** location: ***")
        print(locationManager.location)
        print("--------------------")
        print("*** addressDictionary: ***")
        print(placemark.addressDictionary)
        print("-----END OF UPDATE-----")

    }

    func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
        print("Error: " + error.localizedDescription)

    }
}

【问题讨论】:

    标签: swift geolocation location xcode7 locationmanager


    【解决方案1】:

    使用guard letif let 解开字符串。如果您选择单击placemark 属性,例如subThoroughfare,它会说它是一个可选字符串。

    你也可以像here解释的那样解包

    let subThoroughfare = placemark.subThoroughfare ?? ""
    

    let subThoroughfare = placemark.subThoroughfare ?? "Default subThoroughfare"
    

    完整示例:

        let subThoroughfare = placemark.subThoroughfare ?? ""
        let thoroughfare = placemark.thoroughfare ?? ""
        let subLocality = placemark.subLocality ?? ""
        let locality = placemark.locality ?? ""
        let administrativeArea = placemark.administrativeArea ?? ""
        let postalCode = placemark.postalCode ?? ""
        let country = placemark.country ?? ""
    
        myAddressView.text = " \(subThoroughfare) \(thoroughfare) \r \(subLocality) \r \(locality) \(administrativeArea) \(postalCode) \r \(country)"
    

    解开字符串时使用Nil Coalescing Operator 是有意义的。按照第一个链接了解更多信息。它允许您轻松解开可选字符串或在它为 nil 时使用空/默认字符串。对于几乎所有其他选项,您都需要使用 if letguard let 语句。

    永远不要强制展开可选的(使用! 称为强制展开)从像核心位置这样的框架返回的值。您无法知道所有可能的返回值以及它们何时会或不会为零。只有在创建选项时才强制展开选项,并且绝对确定它们不是零。例如,在分配了一个值之后,可能可以强制展开。


    关于选项:optionals

    关于守卫:guard keyword

    【讨论】:

    • @R Menke 我如何解开 myAddressView.text = " (placemark.subThoroughfare) (placemark.thoroughfare) \r (placemark.subLocality) \r (placemark.locality) (placemark.administrativeArea) ( placemark.postalCode) \r (placemark.country)" 和 myLocationVIew.text = "(locationManager.location)" ?
    • @R Menke 我是 swift 新手,你能告诉我如何实现这个功能,这样两个 UITextfields 就不会显示可选的字符串欢呼声。
    • @GurvierSinghDhillon 不,我使用了您的确切代码。没有实施。 SO 不是 Fix-Your-Code-Squad。我们很乐意帮助您解决具体问题。将其复制粘贴回您自己的代码是您的工作。 (因为认真,尝试复制和粘贴.....)
    • @R Menke 感谢您的帮助和时间先生,它现在正在工作!最受赞赏。
    • @GurvierSinghDhillon 我知道你能做到!欢迎来到 swift 和 SO!
    【解决方案2】:

    它会打印Optional String,因为您尝试打印的变量是Optional 变量,这意味着该变量可能包含值,也可能不包含值。

    如果您确定变量已保存该值,只需在变量末尾添加一个! 即可unwrap

        print(placemark.subThoroughfare!)
        print(placemark.thoroughfare!)
        print(placemark.locality!)
        print(placemark.postalCode!)
        print(placemark.administrativeArea!)
    

    如果不确定,请尝试检查它是否等于nil(使用Nil Coalescing Operator),如果是nil,则打印默认值:

        print(placemark.subThoroughfare ?? "")
        print(placemark.thoroughfare ?? "")
        print(placemark.locality ?? "")
        print(placemark.postalCode ?? "")
        print(placemark.administrativeArea ?? "")
    

    【讨论】:

    • @t4nhp 第二种方法有效,但是我的位置详细信息也显示在 2 个 uitextfields 中,这些也没有展开。例如 myAddressView.text = " (placemark.subThoroughfare) (placemark.thoroughfare) \r (placemark.subLocality) \r (placemark.locality) (placemark.administrativeArea) (placemark.postalCode) \r (placemark.country)" 和myLocationVIew.text = "(locationManager.location)"
    猜你喜欢
    • 1970-01-01
    • 2014-12-31
    • 2015-10-28
    • 2016-07-11
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 2016-01-05
    • 1970-01-01
    相关资源
    最近更新 更多