Cannot get rid of Optional() string

2020-02-02 01:37发布

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?

5条回答
Evening l夕情丶
2楼-- · 2020-02-02 02:12

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...

查看更多
祖国的老花朵
3楼-- · 2020-02-02 02:13

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..
   }
}
查看更多
够拽才男人
4楼-- · 2020-02-02 02:16

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.

查看更多
劫难
5楼-- · 2020-02-02 02:18

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.

查看更多
劳资没心,怎么记你
6楼-- · 2020-02-02 02:27

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.

查看更多
登录 后发表回答