ChatGPT解决这个技术问题 Extra ChatGPT

如何解决“字符串插值为可选值生成调试描述;您是要明确说明吗?”在 Xcode 8.3 测试版中?

从 beta 8.3 开始,zillions 警告“字符串插值会为可选值生成调试描述;您是要明确说明吗?”出现在我的代码中。

例如,在以下情况下会弹出警告,其中 options 可能导致 nil:

let msg = "*** Error \(options["taskDescription"]): cannot load \(sUrl) \(error)"

正如之前设计的那样,我(和编译器)可以将可选项插入为“nil”。但是编译器改变了主意。

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

let msg = "*** Error \(String(describing: options["taskDescription"])): cannot load \(sUrl) \(error)"

显然,结果是明确的,但在我看来也非常繁琐。有更好的选择吗?我必须修复所有这些警告还是更好地等待下一个测试版?

https://i.stack.imgur.com/llT41.png

多么令人讨厌的警告……
Swift 3 破坏了我自己的 log,而我只是使用 print 而犯了一个错误。应该始终创建自己的包装器,否则您会被这种“新功能”搞砸。

H
Hamish

这是在 this pull request 中进行的更改,因为将 Optional(...) 插入到结果字符串中通常是不可取的,并且可能特别令人惊讶 in cases with implicitly unwrapped optionals。您可以在邮件列表 here 上查看有关此更改的完整讨论。

正如在拉取请求讨论中所提到的(尽管不幸不是 Xcode)——一种比使用 String(describing:) 更好的方式来消除警告是向您要插入的任何类型的可选类型添加强制转换,例如:

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

这也可以推广到 as Optional

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 中,使用 SE-0228 引入的新字符串插值系统,另一种选择是为 DefaultStringInterpolation 添加自定义 appendInterpolation 重载:

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}

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

print("description of i: \(optional: i)") // description of i: Optional(5)
print("description of d: \(optional: d)") // description of d: nil

而且,如果需要,您甚至可以删除参数标签以完全禁用模块内的警告(或者如果您将其标记为 fileprivate,则在特定文件内):

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(_ optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}

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

print("description of i: \(i)") // description of i: Optional(5)
print("description of d: \(d)") // description of d: nil

虽然我个人更愿意保留参数标签。


从提案来看,尚不清楚这种变化是否会是永久性的?你怎么看? @哈米什
@StéphanedeLuca 在邮件列表上讨论了很多关于其他解决方案的讨论,例如允许 ?? "nil" 使警告静音,这似乎有点受欢迎,因此可能会在不久的将来出现在另一个提案中。我确实同意这种解决方法不太理想——就个人而言,我认为将 Optional(...) 插入到字符串中作为一个强选项是相当明显的——只有 IUO 的情况才需要这个警告 IMO。但是 Swift 一直在不断发展,所以这一切都可能在以后发生变化。但就目前而言,这就是我们所拥有的。
我还偶然发现了一个有点“相关”的问题,如果您可以看一下,请不要再在这里拆箱stackoverflow.com/questions/42543512/…? @哈米什
...无论如何,这段代码很疯狂:guard result == nil else { print("result was \(result as Optional)") return }
@loretoparisi 为什么不使用 if let?即if let result = result { print("result was \(result)"); return }。并非所有的早期回报都需要与警卫一起完成。
M
Mo Iisa

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

选项1:

第一种是通过“强制展开”您想要使用 bang (!) 返回的值

var someValue: Int? = 5
print(someValue!)

输出:

5

选项 2:

另一种方法,可能是更好的方法 - 是“安全地解开”你想要返回的值。

var someValue: Int? = 5

if let newValue = someValue {
    print(newValue)
}

输出:

5

建议选择选项 2。

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


我是新手,但我喜欢选项 2 在打印前验证包装,并且您总是可以选择在打开包装时打印其他内容
如果您想认真对待,强制展开是不行的。我的意思是仅仅因为你想控制台打印一些东西,你就会冒着应用程序崩溃的风险?这是一个非常糟糕的建议。选项2还可以,我觉得2ht“Tip”不够用,换个答案吧!
b
brian.clear

似乎使用 String(describing:optional) 是最简单的。

默认值 ??对非字符串没有意义,例如 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

C
Community

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

基本上,添加一个可选扩展,它提供一个描述可选内容的字符串,或者如果未设置,则简单地为“nil”。另外,如果 optional 中的东西是一个 String,把它放在引号里。

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"

感谢以下链接的帮助:

check-if-variable-is-an-optional-and-what-type-it-wraps


此解决方案不适用于可选链。像a?.b?.c.orNil
p
pkamb

See Ole Begeman's fix for this。我喜欢它。它创建一个 ??? 运算符,然后您可以像这样使用它:

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"

我认为参考他的博客文章来描述这一点会很有用:oleb.net/blog/2016/12/optionals-string-interpolation
J
Jayprakash Dubey

双击包含此警告的行上显示的黄色三角形。这将显示带有两个解决方案的 FixIt。

https://i.stack.imgur.com/kyzTQ.png

使用 String(describing:) 来消除这个警告:使用它会变成 String(describing:) 例如。 : String(describing: employeeName) 提供一个默认值来避免这个警告 : 使用这个它将变成 ( ?? default value) 例如:employeeName ?? “匿名”为!细绳


是的,我也会选择 Nil-Coalescing 运算符:developer.apple.com/library/content/documentation/Swift/…
很好的答案!如果您要提供替代字符串值,则 Nil-coalescing 可以很好地使用
C
Community

斯威夫特 5

我的解决方案是制作一个将 Optional 对象解包到 Anyextension

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

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>|⭕️

S
ScottyBlades

创建一个插值方法,该方法接受带有未命名参数的可选泛型类型。你所有烦人的警告都会神奇地消失。

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(_ optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅