Cannot get rid of Optional() string

吃可爱长大的小学妹 提交于 2019-12-17 17:08:07

问题


I am trying to update users location on server

Using this function

func updateloc(lat : String?, long : String?) {

/code...

 let data = "lat=\(lat!)&long=\(long!)"

}

And here is the delegate

 func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {


        updateloc(String(manager.location?.coordinate.latitude), long: String(manager.location?.coordinate.longitude))

    }

I have Optional("") for lat and long variables and cannot get rid of it.

Any idea how to do that?


回答1:


If you unwrap the latitude and longitude values like this...

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

    if  let lat = manager.location?.coordinate.latitude,
        let long = manager.location?.coordinate.longitude {

        updateloc(String(lat), long: String(long))
    }
}

...then you can avoid optionals altogether in the updateloc function:

func updateloc(lat : String, long : String) {

// code...

    let data = "lat=\(lat)&long=\(long)"
}

originalUser2 is right...you should get in the habit of safely unwrapping optionals unless you have a really good reason for force-unwrapping them. And just trying to get rid of the optional so the code will compile is not a good reason.




回答2:


updateloc(String(manager.location?.coordinate.latitude), ...)

That code is taking an optional value (manager.location?.coordinate.latitude) and then forcing it to a String. This results in the String "Optional(42.0)" or whatever. It then passes that to updateloc.

I presume that latitude is a Double or similar. You need to handle the optional Double before conversion to a String, something like this:

func coordToString(val: Double?) -> String {
    return (val == nil ? "---" : String(val!))
}

...

updateloc(coordToString(manager.location?.coordinate.latitude), ...)

I often put functions similar to coordToString as an extension on the model object itself (your manager or location). I'd name them formattedLatitude or something like that. That way, all the screens in your app will use the same formatting for that value, because they'll all be using the same code to do it. This keeps rules like 'if the latitude is missing, display "---"' together in one place.




回答3:


Why not checking if the location is not nil

if let currentLocation = manager.location {
   updateloc(String(currentLocation.coordinate.latitude), long: String(currentLocation.coordinate.longitude))
}

and declare updateloc() with non-optional parameters

func updateloc(lat : String, long : String) {...}

And why not

func updateloc(CLLocationCoordinate2D : coordinate) { 
    let data = "lat=\(coordinate.latitude)&long=\(coordinate.longitude)"
} 

if you're using String Interpolation anyway...




回答4:


I think you are updating user's location by making an HTTP request with the latitude and longitude values in the query string or body of the request.

There are couple of options you can try:

  1. Nil coalescing operator

The nil coalescing operator (a ?? b) unwraps an optional a if it contains a value, or returns a default value b if a is nil. The expression a is always of an optional type. The expression b must match the type that is stored inside a.

Assuming we send empty string in the request for any non-existent value:

func updateloc(lat : Double?, long : Double?) {
   let latitude = String(lat) ?? ""
   let longitude = String(long) ?? ""
   let data = "lat=\(latitude)&long=\(longitude)"
   ...
}
  1. Optional binding

You use optional binding to find out whether an optional contains a value, and if so, to make that value available as a temporary constant or variable.

Assuming we don't trigger the request for any non-existent value:

func updateloc(lat : Double?, long : Double?) {
   if let latitude = lat, longitude = long {
      let data = "lat=\(latitude)&long=\(longitude)"
   }
   else {
      // Don't make a request..
   }
}

By the way it is more readable to pass the location as CLLocationCoordinate2D type instead of passing latitude and longitude separately:

func updateloc(coordinate: CLLocationCoordinate2D?) {
   if let coordinate = coordinate {
      let data = "lat=\(coordinate.latitude)&long=\(coordinate.longitude)"
   }
   else {
      // Don't make a request..
   }
}



回答5:


This is not the exact answer to this question, but one reason for this kind of issue.

In my case, I was not able to remove Optional from a String with "if let" and "guard let".

I case of Any

        let dict1 : [String:Any] = ["key":("value" as String?) as Any]

      //use guard let, if let, default value but the string is still optional
         if let a = dict1["key"] {
                print("With Any \(a)")
            }

    //Output is: With Any Optional("value")

In case of AnyObject

    let dict : [String:AnyObject] = ["key":("value" as String?) as AnyObject]
        if let a = dict["key"] {
                print("With AnyObject \(a)")
            }

    //Output is: With AnyObject value

So use AnyObject instead of Any to remove optional from a string in swift.



来源:https://stackoverflow.com/questions/36432655/cannot-get-rid-of-optional-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!