Swift 如何解决;字符串插值生成可选值的调试说明;你的意思是说得很清楚吗;在Xcode 8.3测试版中?

Swift 如何解决;字符串插值生成可选值的调试说明;你的意思是说得很清楚吗;在Xcode 8.3测试版中?,swift,swift3,optional,string-interpolation,Swift,Swift3,Optional,String Interpolation,自beta 8.3以来,我的代码中出现了无数警告“字符串插值生成可选值的调试说明;您的意思是要使其显式化吗?” 例如,在以下情况下弹出警告,选项可能导致零: let msg = "*** Error \(options["taskDescription"]): cannot load \(sUrl) \(error)" 按照之前的设计,我(和编译器)可以将选项插值为“nil”。但编译器改变了主意 编译器建议添加一个字符串构造函数,其描述如下: let msg = "*** Error \(St

自beta 8.3以来,我的代码中出现了无数警告“字符串插值生成可选值的调试说明;您的意思是要使其显式化吗?”

例如,在以下情况下弹出警告,选项可能导致零:

let msg = "*** Error \(options["taskDescription"]): cannot load \(sUrl) \(error)"
按照之前的设计,我(和编译器)可以将选项插值为“nil”。但编译器改变了主意

编译器建议添加一个字符串构造函数,其描述如下:

let msg = "*** Error \(String(describing: options["taskDescription"])): cannot load \(sUrl) \(error)"
显然,结果是明确的,但在我看来也是非常麻烦的。有更好的选择吗?我必须修复所有这些警告,还是最好等到下一个测试版


这是一个更改,因为在结果字符串中插入
可选(…)
通常是不可取的,并且可能特别令人惊讶。您可以在邮件列表中看到有关此更改的完整讨论

正如拉入请求讨论中所提到的(尽管不幸的是不是通过Xcode)——与使用
String(description:)
相比,让警告静音的一种稍微好一点的方法是向要插值的任意对象的可选类型添加强制转换,例如:

var i: Int? = 5
var d: Double? = nil

print("description of i: \(i as Int?)")    // description of i: Optional(5)
print("description of d: \(d as Double?)") // description of d: nil
也可以将其概括为可选的

print("description of i: \(i as Optional)") // description of i: Optional(5)
print("description of d: \(d as Optional)") // description of d: nil
在Swift 5中,由于引入了新的字符串插值系统,另一个选项是为以下对象添加自定义
appendInterpolation
重载:

虽然我个人更喜欢保留参数标签。

似乎使用字符串(描述:可选)是最简单的

默认值??对于非字符串(例如Int)没有意义。
如果Int为nil,则希望日志显示“nil”,而不是默认为另一个Int,例如0

要测试的一些代码:

var optionalString : String? = nil
var optionalInt : Int? = nil

var description_ = ""
description_ = description_ + "optionalString: \(String(describing: optionalString))\r"
description_ = description_ + "   optionalInt: \(String(describing: optionalInt))\r"

print(description_)
输出

optionalString: nil
optionalInt: nil

在升级到Xcode 8.3并收到大量警告消息后,我提出了以下内容,它更像原始的输出行为,易于添加,减少了在代码和输出中使用“String(description:)”的冗长性

基本上,添加一个可选扩展名,该扩展名在可选扩展名中提供一个描述对象的字符串,如果未设置,则简单地说是“nil”。此外,如果可选项中的内容是字符串,请将其置于引号中

extension Optional {
    var orNil : String {
        if self == nil {
            return "nil"
        }
        if "\(Wrapped.self)" == "String" {
            return "\"\(self!)\""
        }
        return "\(self!)"
    }
}
以及在游乐场的使用:

var s : String?
var i : Int?
var d : Double?

var mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = nil    i = nil   d = nil"

d = 3
i = 5
s = ""
mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = ""    i = 5   d = 3.0"

s = "Test"
d = nil
mixed = "s = \(s.orNil)    i = \(i.orNil)   d = \(d.orNil)" // "s = "Test"    i = 5   d = nil"
感谢以下链接提供的帮助:

。我喜欢它。它创建了一个
操作符,您可以这样使用它:

var someValue: Int? = 5
print("The value is \(someValue ??? "unknown")")
// → "The value is 5"
someValue = nil
print("The value is \(someValue ??? "unknown")")
// → "The value is unknown"

双击包含此警告的行上显示的黄色三角形。这将显示具有两种解决方案的修复

  • 使用
    字符串(描述:)
    使此警告静音:

    使用此选项,它将变成
    字符串(描述:)

    例如:
    String(描述:employeeName)

  • 提供
    默认值
    以避免此警告:

    使用此选项将成为
    (?默认值)

    例如:
    employeeName??“匿名”为!字符串


  • 处理这个问题有两种更简单的方法

    选项1:

    第一种方法是“强制展开”希望使用bang(!)返回的值

    输出:

    5
    
    5
    
    选项2:

    另一种可能更好的方法是“安全地展开”要返回的值

    var someValue: Int? = 5
    
    if let newValue = someValue {
        print(newValue)
    }
    
    输出:

    5
    
    5
    
    我建议选择方案2

    提示:尽可能避免强制展开(!),因为我们不确定是否始终具有要展开的值

    斯威夫特5 我的解决方案是制作一个
    扩展
    ,它将
    可选
    对象展开到
    任意

    当您记录或打印对象时,您可以看到实际的
    对象
    ⭕️(文本和可视字符的组合)。查看它很有用,尤其是在控制台日志中

    extension Optional {
        var logable: Any {
            switch self {
            case .none:
                return "<nil>|⭕️"
            case let .some(value):
                return value
            }
        }
    }
    
    // sample
    var x: Int?
    print("Logging optional without warning: \(x.logable)")
    // → Logging optional without warning: <nil>|⭕️
    
    扩展名可选{
    可记录变量:任何{
    切换自身{
    案例:无:
    返回“|⭕️"
    一些(值):
    返回值
    }
    }
    }
    //样品
    var x:Int?
    打印(“在没有警告的情况下记录可选:\(x.logable)”)
    // → 在没有警告的情况下记录日志是可选的:|⭕️
    
    创建一个插值方法,该方法接受带有未命名参数的可选泛型类型。所有恼人的警告将神奇地消失

    extension DefaultStringInterpolation {
      mutating func appendInterpolation<T>(_ optional: T?) {
        appendInterpolation(String(describing: optional))
      }
    }
    
    扩展默认字符串插值{
    变异函数插值(u可选:T?){
    追加插值(字符串(描述:可选))
    }
    }
    
    从提案来看,不清楚这一变化是否将是永久性的?您认为如何@Hamish@StéphanedeLuca邮件列表上有很多关于其他解决方案的讨论,比如允许
    ?“nil”“
    使这一似乎颇受欢迎的警告保持沉默,因此可能会在不久的将来出现在另一个提案中。我确实同意这种解决方法并不理想——就我个人而言,我觉得很明显希望
    Optional(…)
    被插入到强可选字符串中——事实上,只有IUO才需要这种警告。但Swift在不断发展,因此这一切可能在以后的过程中发生变化。但就目前而言,这就是我们所拥有的。我还偶然发现了一个“相关”的问题,如果你能看一看的话,请不要在这里拆箱@Hamish…在任何情况下,此代码都是疯狂的:
    guard result==nil else{print(“result was\(result as Optional)”)return}
    @loretoparisi如果let
    ,为什么不使用
    ?i、 e
    如果let result=result{print(“result was\(result)”);return}
    。并非所有的提前归还都需要警卫。这真是一个恼人的警告…
    Swift 3
    打破了我自己的
    log
    ,我只是用了
    print就犯了一个错误
    
    extension DefaultStringInterpolation {
      mutating func appendInterpolation<T>(_ optional: T?) {
        appendInterpolation(String(describing: optional))
      }
    }