Thanks to SE-0228, you can control exactly how you want string interpolations to print. Thank you Brent for giving this to us. It’s a doozy! Let me share some examples.
Consider printing optionals. You use:
"There's \(value1) and \(value2)"
And get an instant warning:
You can click the fixes to suppress the warning but you’ll still get an output that looks like this: “There’s Optional(23) and nil”.
"There's \(String(describing: value1)) and \(String(describing: value2))"
Now you can strip the “Optional” and produce “There’s 23 and nil”, allowing you to print values directly:
extension String.StringInterpolation { /// Provides `Optional` string interpolation without forcing the /// use of `String(describing:)`. public mutating func appendInterpolation(_ value: T?, default defaultValue: String) { if let value = value { appendInterpolation(value) } else { appendLiteral(defaultValue) } } } // There's 23 and nil "There's \(value1, default: "nil") and \(value2, default: "nil")"
You might create a set of styles and custom interpolation to support consistent presentation for optional output:
extension String.StringInterpolation { /// Optional Interpolation Styles public enum OptionalStyle { /// Includes the word `Optional` for both `some` and `none` cases case descriptive /// Strips the word `Optional` for both `some` and `none` cases case stripped /// Uses system interpolation, which includes the word `Optional` for /// `some` cases but not `none`. case `default` } /// Interpolates optional values using a supplied `optStyle` style public mutating func appendInterpolation(_ value: T?, optStyle style: String.StringInterpolation.OptionalStyle) { switch style { // Includes the word `Optional` for both `some` and `none` cases case .descriptive: if value == nil { appendLiteral("Optional(nil)") } else { appendLiteral(String(describing: value)) } // Strips the word `Optional` for both `some` and `none` cases case .stripped: if let value = value { appendInterpolation(value) } else { appendLiteral("nil") } // Uses system interpolation, which includes the word `Optional` for // `some` cases but not `none`. default: appendLiteral(String(describing: value)) } } /// Interpolates an optional using "stripped" interpolation, omitting /// the word "Optional" from both `.some` and `.none` cases public mutating func appendInterpolation (describing value: T?) { appendInterpolation(value, optStyle: .stripped) } } // "There's Optional(23) and nil" "There's \(value1, optStyle: .default) and \(value2, optStyle: .default)" // "There's Optional(23) and Optional(nil)" "There's \(value1, optStyle: .descriptive) and \(value2, optStyle: .descriptive)" // "There's 23 and nil" "There's \(describing: value1) and \(describing: value2)"
Interpolation isn’t limited to tweaking optionals. Say you want to control whether a string is added without having to use a ternary expression with an empty string:
// Include on success (Thanks, Nate Cook) extension String.StringInterpolation { /// Provides Boolean-guided interpolation that succeeds only when the condition /// evaluates to true. mutating func appendInterpolation(if condition: @autoclosure () -> Bool, _ literal: StringLiteralType) { guard condition() else { return } appendLiteral(literal) } } // Old "Cheese Sandwich \(isStarred ? "(*)" : "")" // New "Cheese Sandwich \(if: isStarred, "(*)")"
There’s lots more you can do and it’s all exciting and fun.
2 Comments
Great post on a simple example of this new Swift 5 feature. I posted this blog post on my local iOS developer FB group.
However I have a question, regarding calling `appendLiteral` in your example. When or should we call this `appendLiteral` method directly in the appendInterpolation method implementation? There is a comment saying that we should not call this `appendLiteral` method directly in the code example in the SE.
Great blog post about a simple example for the new String Interpolation use cases in Swift 5. I posted this post on our local iOS developer FB group.
However I saw a comment in the code example in the SE saying that we shouldn’t call `appendLiteral` method directly but I see you call it in your appendInterpolation method implementation. So I want to ask you should we call or when can we call this method directly?