解決方法「文字列補間は、オプション値のデバッグ記述を生成します。これを明示するつもりでしたか?」Xcode 8.3ベータ版では?


87

ベータ8.3以降、無数の警告「文字列補間はオプション値のデバッグ記述を生成します。これを明示的にするつもりでしたか?」私のコードに現れました。

たとえば、次の状況で警告が表示され、オプションがnilになる可能性があります。

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

以前に設計したように、私(およびコンパイラ)はオプションを「nil」として補間しても問題ありませんでした。しかし、コンパイラは考えを変えました。

コンパイラーが提案するのは、次のような説明を含むStringコンストラクターを追加することです。

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

明らかに、結果は明白ですが、私の意見では非常に面倒でもあります。より良いオプションはありますか?これらの警告をすべて修正する必要がありますか、それとも次のベータ版を待つ必要がありますか?

説明のスクリーンショット


26
どのような本当に迷惑な警告...
ジョニー

Swift 3私は自分自身logを壊し、print代わりに使用するだけで間違いを犯しました。常に独自のラッパーを作成する必要があります。そうしないと、この種の「新機能」に悩まされることになります。
superarts.org 2017

回答:


105

これは、結果の文字列への補間が望ましくない場合が多く、暗黙的にラップされていないオプションがある場合に特に驚く可能性があるため、このプルリクエストで行われた変更です。この変更の詳細については、こちらのメーリングリストをご覧くださいOptional(...)

プルリクエストの説明で述べたように(残念ながらXcodeではありませんが)–を使用するよりも警告を消すための少し良い方法の1つ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によって導入された新しい文字列補間システムで、別のオプションは次のカスタムappendInterpolationオーバーロードを追加することですDefaultStringInterpolation

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

個人的には、引数のラベルを付けておきたいと思います。


提案から、この変更が永続的であるかどうかは明らかではありませんか?どう思いますか?@Hamish
ステファン・デ・ルカ

@StéphanedeLucaメーリングリストで?? "nil"は、警告を消すなど、あまり人気がないように思われる他の解決策についてかなりの議論があったため、近い将来、別の提案に登場する可能性があります。この回避策は理想的ではないことに同意します。個人的にOptional(...)は、強力なオプションの文字列に補間されることを期待するのはかなり明白だと思います。この警告IMOが必要なのはIUOの場合だけでした。しかし、Swiftは常に進化しているため、これはすべて後で変更される可能性があります。しかし今のところ、それは私たちが持っているものです。
ハミッシュ2017年

聞かせてはもうここにアンボクシングされていない場合、私はまたしてやや「関連」の問題につまずいstackoverflow.com/questions/42543512/...あなたが見ることができますか?@Hamish
ステファン・デ・ルカ

...いずれにせよ、このコードはクレイジーです:guard result == nil else { print("result was \(result as Optional)") return }
loretoparisi 2017

1
@loretoparisi使ってみませんif letか?すなわちif let result = result { print("result was \(result)"); return }。すべての早期返品を警備員が行う必要はありません。
ハミッシュ2017

29

この問題に対処する2つの簡単な方法。

オプション1:

1つ目は 、バング(!)を使用して返したい値を「強制アンラップ」することです

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

出力:

5

オプション2:

もう1つの方法は、より良い方法である可能性があります。返される値を「安全にアンラップ」することです。

var someValue: Int? = 5

if let newValue = someValue {
    print(newValue)
}

Output:

5

Would recommend to go with option 2.

Tip: Avoid force unwrapping (!) where possible as we are not sure if we will always have the value to be unwrapped.


1
I am new but I like the option 2 to validate the wrapping before print and you always have an option to print something else when it is unwrapped
AbuTaareq

16

seems using String(describing:optional) is simplest.

default value ?? makes no sense for non-Strings e.g Int.
If Int is nil then you want the log to show 'nil' not default to another Int e.g. 0.

Some playground code to test:

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

Output

optionalString: nil
optionalInt: nil

13

After updating to Xcode 8.3 and getting a lot of warning messages, I came up with the following that is more like the original output behavior, easy to add in, reduces the verboseness of using "String(describing:)" both in code and output.

Basically, add an Optional extension that gives a String describing the thing in the optional, or simply "nil" if not set. In addition, if the thing in the optional is a String, put it in quotes.

extension Optional {
    var orNil : String {
        if self == nil {
            return "nil"
        }
        if "\(Wrapped.self)" == "String" {
            return "\"\(self!)\""
        }
        return "\(self!)"
    }
}

And usage in a playground:

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"

Thanks for help from following link:

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


This solution not working in optional chain. Like a?.b?.c.orNil.
Vincent Sit


8

Double click on the yellow triangle displayed on line containing this warning. This will show FixIt with two solutions.

Screenshot added

  1. Use String(describing:) to silence this warning :

    Using this it will become String(describing:<Variable>)

    Eg. : String(describing: employeeName)

  2. Provide a default value to avoid this warning :

    Using this it will become (<Variable> ?? default value)

    Eg.: employeeName ?? “Anonymous” as! String


1
Yes, i would also go for the Nil-Coalescing Operator: developer.apple.com/library/content/documentation/Swift/…
kevinius

1
Great answer! Nil-coalescing works well with this if you have an alternative string value to provide
Lance Samaria

1

Swift 5

My solution is making an extension which unwrap Optional object to Any.

When you log the object or print it out, you can see the actual object or <nil>⭕️ (combination from text and visual character). It's useful to look at, especially in the console log.

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

0

Create an interpolation method that accepts an optional generic Type with an unnamed parameter. All your annoying warnings will magically disappear.

extension DefaultStringInterpolation {
  mutating func appendInterpolation<T>(_ optional: T?) {
    appendInterpolation(String(describing: optional))
  }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.