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

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?

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.

Why is my label displaying Your cat is Optional(35) years old when it should display Your cat is 35 years old?

The problem is here:

String(describing: catYears)

catYears is an Optional<Int>, a string that describes an Optional<Int> will be in the format of Optional(<value>) or nil. That's why you get Optional(35).

You need to unwrap catYears!

String(describing: catYears!)

Or, remove String(describing:) all together and do:

if let humanYearsText = getHumanYears.text, let humanYears = Int(humanYearsText)
{
let catYears = humanYears * 7
displayCatYears.text = "Your cat is \(catYears) years old"
}

Why 'if let' does not seem to unbox a value as before in Swift 3 in Xcode 8.3 beta?

Ok then doing that for example solves the issue:

if let item = item as? [String: String?], let title = item["label"] ?? nil {
/* … */
}

How to fix the warning of type casting in 'if let' statement in Xcode 8.3?

Try to cast to an optional Date:

if let date = nsdate as Date?

You're trying to optional cast of optional NSDate to NON optional Date. As long as NSDate is bridged from obj-c to Date, so this cast always success, so no optional cast required here, just basic cast as is enough. Then you need to cast optional value, so the resulting value has to be optional too, therefore Date? is appropriate here.

Ternary operator and unwrapping with SwiftLint

I would map the optional to the interpolated string, and use ?? to provide the default value:

let display = subtype.map { "\(rawValue) (\($0))" } ?? rawValue

Why can't I use single equals(=) as part of my while loop condition?

The reason for the error with

while (responder = responder.next!) {

is that the only thing permitted after the keyword while is a condition, and the only thing that a condition can be is an expression that evaluates to a Bool. An assignment cannot be a Bool.


What you're trying to do is perfectly reasonable; I do it all the time. Here's my formulation:

    var r : UIResponder! = view
repeat { r = r.next } while !(r is UIViewController)
let vc = r as! UIViewController

You'll notice I don't check for nil at all in that formulation; if we reach the end of the responder chain without finding a view controller, something is very wrong and I want to crash.

Another formulation I use just walks the whole chain and prints it; in that one, I do check for nil, obviously:

    var r : UIResponder! = someResponder
repeat { print(r as Any, "\n"); r = r.next } while r != nil

String property returning different values when used directly or in string interpolation

I feel like this is somewhat similar to the solution of this question of mine. In that question, there is also two almost identical properties - one optional, the other non-optional. And I experienced a similar situation where Swift can't figure out which property I want.

Your titleString in SomeClass is not overriding the titleString property in the protocol. This is reflected in Xcode's suggestions:

Sample Image

You can access both properties like this:

someObject.titleString as String // accesses the one in SomeClass
someObject.titleString as String? // accesses the one in the protocol

My point here is that the type of the expression matters. If the type of expression swift expects is String, then it resolves to the one in SomeClass. If the expected type of the expression is String?, then it evaluates to the one in the protocol.

This explains why setting the label's text without string interpolation will call the property in the protocol (label.text is String?, so it expects a String?) and why using string interpolation will call the property in SomeClass (String interpolation expects a non-optional).



Related Topics



Leave a reply



Submit