【问题标题】:Cannot get rid of Optional() string无法摆脱 Optional() 字符串
【发布时间】:2023-11-26 07:05:01
【问题描述】:

我正在尝试更新服务器上的用户位置

使用此功能

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

/code...

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

}

这是代表

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


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

    }

我有 latlong 变量的 Optional("") 并且无法摆脱它。

知道怎么做吗?

【问题讨论】:

  • 不要强制展开。曾经。你应该学习如何properly deal with optionals.
  • @originaluser2 “曾经”?这一点帮助都没有。它在语言中是有原因的,在很多情况下你都需要它。
  • @EwanMellor 好吧,也许有 一对 边缘情况可以强制展开是可以的......但是当从可选选项开始时,避免像瘟疫那样强制展开是要走的路。

标签: ios swift cllocationmanager


【解决方案1】:

如果你像这样解开纬度和经度值......

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

...那么您可以在 updateloc 函数中完全避免使用选项:

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

// code...

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

originalUser2 是对的……你应该养成安全解包选项的习惯,除非你有充分的理由强制解包它们。只是试图摆脱可选的,以便代码能够编译并不是一个好的理由。

【讨论】:

    【解决方案2】:

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

    该代码采用可选值 (manager.location?.coordinate.latitude),然后将其强制为字符串。这导致字符串"Optional(42.0)" 或其他。然后将其传递给updateloc

    我认为 latitude 是 Double 或类似的。您需要在转换为字符串之前处理可选的 Double,如下所示:

    func coordToString(val: Double?) -> String {
        return (val == nil ? "---" : String(val!))
    }
    
    ...
    
    updateloc(coordToString(manager.location?.coordinate.latitude), ...)
    

    我经常将类似于coordToString 的函数作为模型对象本身的扩展(您的managerlocation)。我会将它们命名为formattedLatitude 或类似的名称。这样一来,您应用程序中的所有屏幕都会对该值使用相同的格式,因为它们都将使用相同的代码来执行此操作。这保留了诸如“如果缺少纬度,则在一个位置显示“---”之类的规则。

    【讨论】:

    • 返回 val?.description ?? “---”
    【解决方案3】:

    为什么不检查位置是否不是nil

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

    并使用非可选参数声明updateloc()

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

    为什么不

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

    如果你仍然使用字符串插值......

    【讨论】:

      【解决方案4】:

      我认为您正在通过使用查询字符串或请求正文中的纬度和经度值发出 HTTP 请求来更新用户的位置。

      您可以尝试以下几个选项:

      1. Nil coalescing operator

      nil 合并运算符 (a ?? b) 解包可选的 a 如果它包含一个值,或者返回一个默认值 b如果 anil。表达式 a 始终是可选类型。 b 表达式必须与 a 中存储的类型匹配。

      假设我们在请求中为任何不存在的值发送空字符串:

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

      您使用可选绑定来确定可选是否包含值,如果是,则将该值作为临时常量或变量提供。

      假设我们没有触发对任何不存在值的请求:

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

      顺便说一下,将位置传递为CLLocationCoordinate2D 类型而不是分别传递纬度和经度更易读:

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

      【讨论】:

        【解决方案5】:

        这不是该问题的确切答案,而是此类问题的一个原因。

        就我而言, 我无法使用“if let”和“guard let”从字符串中删除 Optional。

        任何的情况

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

        如果是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
        

        所以使用 AnyObject 而不是 Any 在 swift 中从字符串中删除可选项。

        【讨论】: