ChatGPT解决这个技术问题 Extra ChatGPT

How to solve "String interpolation produces a debug description for an optional value; did you mean to make this explicit?" in Xcode 8.3 beta?

Since beta 8.3, zillions warnings "String interpolation produces a debug description for an optional value; did you mean to make this explicit?" appeared in my code.

For example, the warning popped in the following situation up, where options could lead to nil:

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

As previously designed, it was ok for me (and the compiler) the optionals to be interpolated as 'nil'. But compiler changed its mind.

What the compiler suggests is to add a String constructor with description as follows:

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

Obviously, the results is explicit but also very very cumbersome in my opinion. Is there a better option? Do I have to fix all those warning or better wait for the next beta?

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

What a truly annoying warning...
Swift 3 broke my own log and I made a mistake by simply using print instead. Should always create your own wrapper otherwise you'll be screwed by this sort of "new feature".

H
Hamish

This is a change that was made in this pull request due to the fact that interpolating Optional(...) into the resultant string is often undesirable, and can be especially surprising in cases with implicitly unwrapped optionals. You can see the full discussion of this change on the mailing list here.

As mentioned in the pull request discussion (although unfortunately not by Xcode) – one slightly nicer way to silence the warning than the use of String(describing:) is to add a cast to the optional type of whatever you're interpolating, so for example:

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

Which can also be generalised to 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

In Swift 5, with the new string interpolation system introduced by SE-0228, another option is to add a custom appendInterpolation overload for 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

And, if desired, you could even remove the argument label to disable the warning entirely within a module (or within a particular file if you mark it as 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

Though personally I would prefer to keep the argument label.


From the proposal, it is not clear whether this change is going to be permanent? What do you think? @Hamish
@StéphanedeLuca There was quite a bit of discussion on the mailing list about other solutions such as allowing for ?? "nil" to silence the warning, which seemed to be mildly popular, so might show up in another proposal in the near future. I do agree that this workaround is less than ideal – personally, I feel it's rather obvious to expect Optional(...) to be interpolated into the string for a strong optional – it was only really the case of IUOs that needed this warning IMO. But Swift is constantly evolving, so this may all change later down the line. But for now, it's what we've got.
I also stumbled upon a somewhat 'related' issue in an if let not unboxing anymore here stackoverflow.com/questions/42543512/… if you can have a look? @Hamish
...in any case this code is crazyness: guard result == nil else { print("result was \(result as Optional)") return }
@loretoparisi Why not use if let? i.e if let result = result { print("result was \(result)"); return }. Not all early returns need to be done with guards.
M
Mo Iisa

Two easier ways of dealing with this issue.

Option 1:

The first would be by "force-unwrapping" the value you would like to return using a bang (!)

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

Output:

5

Option 2:

The other way, which could be the better way - is to "safely-unwrap" the value you want returned.

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.


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
force unwrapping is a NO-GO if you want to take this serious. I mean just because you want to console print something you go into the risk of crashing the app? Thats a very bad suggestion. Option 2 is okay, I think 2ht "Tip" is not sufficient, change the anwer!
b
brian.clear

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

C
Community

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

See Ole Begeman's fix for this. I love it. It creates a ??? operator which you can then use like 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"

A reference to his blog post describing this would be useful I think: oleb.net/blog/2016/12/optionals-string-interpolation
J
Jayprakash Dubey

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

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

Use String(describing:) to silence this warning : Using this it will become String(describing:) Eg. : String(describing: employeeName) Provide a default value to avoid this warning : Using this it will become ( ?? default value) Eg.: employeeName ?? “Anonymous” as! String


Yes, i would also go for the Nil-Coalescing Operator: developer.apple.com/library/content/documentation/Swift/…
Great answer! Nil-coalescing works well with this if you have an alternative string value to provide
C
Community

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

S
ScottyBlades

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

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

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now