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