问题
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:
- 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)"
...
}
- 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