Swift 2 - Optional Strings Appear upon Automatic Location

Gurvier Singh Dhillon

I have an automatic location function in my app but since I updated to swift 2 I started to get the "Optional String" that appears before displaying the location details for each section, any suggestions on how to fix this?

Here is what it shows:

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)

Here is my code below

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)

    }
}
R Menke

Unwrap the strings with guard let or if let. If you option click on a placemark attribute like subThoroughfare it will say it is an optional string.

You can also unwrap like explained here

let subThoroughfare = placemark.subThoroughfare ?? ""

or

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

Full example :

    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)"

When unwrapping strings it makes sense to use the Nil Coalescing Operator. Follow the first link for more info. It allows you to easily unwrap the optional string or use an empty/default string when it is nil. For almost all other optionals you will want to use an if let or guard let statement.

Never force unwrap optional (using ! is called force unwrapping) values returned from an Framework like Core Location. There is no way for you to know all possible return values and when they will or will not be nil. Only ever force unwrap optionals when you created them and are absolutely sure they are not nil. For example, just after assigning a value it might be ok to force unwrap.


About optionals: optionals

About guard: guard keyword

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Optional chaining with Swift strings

From Dev

Proper way to concatenate optional swift strings?

From Dev

Remove Optional("string") in Swift 2

From Dev

Same location 2 buttons in swift?

From Dev

Automatic backup using deja dup on 2 location: locally and usbdrive

From Dev

Swift with Core Data getting an "Optional("")" on the strings i am fetching?

From Dev

Swift 2 parse Json as Optional to array

From Dev

Ambiguous use of "init" with optional arguments in Swift 2

From Dev

Swift 2 Unable to remove optional binding

From Dev

How to use optional binding in Swift 2

From Dev

Swift 2: !, ? -" Value of optional type "..." not unwrapped"

From Dev

Swift2: return a optional type object

From Dev

Swift 2 Unable to remove optional binding

From Dev

Swift Optional of Optional

From Dev

Mutate swift array of strings (swift 2)

From Dev

How make teasers appear upon an image and not behind

From Dev

swift 2 block the running of program if location is off

From Dev

is automatic unchecking of 'optional installs' possible?

From Dev

Automatic acronyms of strings in R

From Dev

Swift/Xcode6: "found nil unwrapping optional" for my user's location

From Dev

Trying to find users location in Xcode with Swift on starting the app but having optional error?

From Dev

Swift2 UI Test - Wait for Element to Appear

From Dev

Upon mousedown, grab children's (numeric) location

From Dev

Match Strings with optional data

From Dev

mapview autozoom on current location automatic

From Dev

Automatic object changes memory location

From Dev

How to stop automatic updates of Location

From Dev

Swift: Optional Text In Optional Value

From Dev

Swift Get string between 2 strings in a string

Related Related

HotTag

Archive