Swift 条件字符串插值
Swift Conditional String Interpolation
当我需要根据某些条件(在本例中为 isFavorite)构建字符串时,我经常陷入这样的代码编写过程中:
let me = Contact(name: "Stefan", isFavorite: true)
var message = "Contact \(me.name)"
if me.isFavorite {
message.append(" is a favorite contact")
}
对于这样一个简单的任务,这些是 4 行或者复杂的三元运算符(if ? then : else)。对此我一直心存愧疚...
有没有办法用 Swift 更优雅地做到这一点?
Swift 5
确实有 - 我在 UIKonf 2019 上找到了答案,我从 Erica Sadun 那里听说有一种方法可以通过使用 Swift 5 String Interpolation
在一行中实现这一点。您只需要这个可重复使用的扩展:
extension String.StringInterpolation {
mutating func appendInterpolation(if condition: @autoclosure () -> Bool, _ literal: StringLiteralType) {
guard condition() else { return }
appendLiteral(literal)
}
}
它使您能够将 4 行转换为一行:
"Contact: \(me.name)\(if: me.isFavorite, " is a favorite contact")"
您可以在 Erica 的文章中阅读 Swift 的字符串插值的不同可能性:https://ericasadun.com/2018/12/12/the-beauty-of-swift-5-string-interpolation/
游乐场
开始动手做这个:
import Foundation
// *****************************************************************************
// Many thanks to Erica Sadun for describing the new possibilities of string
// interpolation in Swift 5
// *****************************************************************************
// *****************************************************************************
// Conditional Interpolation
struct Contact {
let name: String
let isFavorite: Bool
}
let me = Contact(name: "Stefan", isFavorite: true)
// ***************************************************************** Swift 4
var message = "Contact \(me.name)"
if me.isFavorite {
message.append(" is favorite")
}
message // we need 4 lines to construct this message!!!
"Contact: \(me.name)\(me.isFavorite ? " is favorite" : "")" // or a complex ternary operator
// ***************************************************************** Swift 5
extension String.StringInterpolation {
mutating func appendInterpolation(if condition: @autoclosure () -> Bool, _ literal: StringLiteralType) {
guard condition() else { return }
appendLiteral(literal)
}
}
"Contact: \(me.name)\(if: me.isFavorite, " is favorite")" // simple and clean - no extras
// *****************************************************************************
// Optional Interpolation
let optionalMe: Contact? = Contact(name: "Stefan", isFavorite: true)
// ***************************************************************** Swift 4
"Contact: \(optionalMe?.name)" // shows warning
// ***************************************************************** Swift 5
// Interpolate nil value
extension String.StringInterpolation {
/// Provides `Optional` string interpolation without forcing the
/// use of `String(describing:)`.
public mutating func appendInterpolation<T>(_ value: T?, default defaultValue: String) {
if let value = value {
appendInterpolation(value)
} else {
appendLiteral(defaultValue)
}
}
}
let nilContact: Contact? = nil
"Contact: \(nilContact?.name, default: "nil")"
// Strip `Optional`
extension String.StringInterpolation {
/// Interpolates an optional using "stripped" interpolation, omitting
/// the word "Optional" from both `.some` and `.none` cases
public mutating func appendInterpolation<T>(describing value: T?) {
if let value = value {
appendInterpolation(value)
} else {
appendLiteral("nil")
}
}
}
"Contact: \(describing: optionalMe?.name)"
您可以使用Ternary operator
let msg = "Contact \(me.name)" + (me.isFavorite ? " is a favorite contact" : "")
我倾向于创建第二个 String
变量,它可能为空也可能不为空,然后无条件地附加它...
let me = Contact(name: "Stefan", isFavorite: true)
let favorite = me.isFavorite ? " is a favorite contact" : ""
var message = "Contact \(me.name)\(favorite)"
当我需要根据某些条件(在本例中为 isFavorite)构建字符串时,我经常陷入这样的代码编写过程中:
let me = Contact(name: "Stefan", isFavorite: true)
var message = "Contact \(me.name)"
if me.isFavorite {
message.append(" is a favorite contact")
}
对于这样一个简单的任务,这些是 4 行或者复杂的三元运算符(if ? then : else)。对此我一直心存愧疚...
有没有办法用 Swift 更优雅地做到这一点?
Swift 5
确实有 - 我在 UIKonf 2019 上找到了答案,我从 Erica Sadun 那里听说有一种方法可以通过使用 Swift 5 String Interpolation
在一行中实现这一点。您只需要这个可重复使用的扩展:
extension String.StringInterpolation {
mutating func appendInterpolation(if condition: @autoclosure () -> Bool, _ literal: StringLiteralType) {
guard condition() else { return }
appendLiteral(literal)
}
}
它使您能够将 4 行转换为一行:
"Contact: \(me.name)\(if: me.isFavorite, " is a favorite contact")"
您可以在 Erica 的文章中阅读 Swift 的字符串插值的不同可能性:https://ericasadun.com/2018/12/12/the-beauty-of-swift-5-string-interpolation/
游乐场
开始动手做这个:
import Foundation
// *****************************************************************************
// Many thanks to Erica Sadun for describing the new possibilities of string
// interpolation in Swift 5
// *****************************************************************************
// *****************************************************************************
// Conditional Interpolation
struct Contact {
let name: String
let isFavorite: Bool
}
let me = Contact(name: "Stefan", isFavorite: true)
// ***************************************************************** Swift 4
var message = "Contact \(me.name)"
if me.isFavorite {
message.append(" is favorite")
}
message // we need 4 lines to construct this message!!!
"Contact: \(me.name)\(me.isFavorite ? " is favorite" : "")" // or a complex ternary operator
// ***************************************************************** Swift 5
extension String.StringInterpolation {
mutating func appendInterpolation(if condition: @autoclosure () -> Bool, _ literal: StringLiteralType) {
guard condition() else { return }
appendLiteral(literal)
}
}
"Contact: \(me.name)\(if: me.isFavorite, " is favorite")" // simple and clean - no extras
// *****************************************************************************
// Optional Interpolation
let optionalMe: Contact? = Contact(name: "Stefan", isFavorite: true)
// ***************************************************************** Swift 4
"Contact: \(optionalMe?.name)" // shows warning
// ***************************************************************** Swift 5
// Interpolate nil value
extension String.StringInterpolation {
/// Provides `Optional` string interpolation without forcing the
/// use of `String(describing:)`.
public mutating func appendInterpolation<T>(_ value: T?, default defaultValue: String) {
if let value = value {
appendInterpolation(value)
} else {
appendLiteral(defaultValue)
}
}
}
let nilContact: Contact? = nil
"Contact: \(nilContact?.name, default: "nil")"
// Strip `Optional`
extension String.StringInterpolation {
/// Interpolates an optional using "stripped" interpolation, omitting
/// the word "Optional" from both `.some` and `.none` cases
public mutating func appendInterpolation<T>(describing value: T?) {
if let value = value {
appendInterpolation(value)
} else {
appendLiteral("nil")
}
}
}
"Contact: \(describing: optionalMe?.name)"
您可以使用Ternary operator
let msg = "Contact \(me.name)" + (me.isFavorite ? " is a favorite contact" : "")
我倾向于创建第二个 String
变量,它可能为空也可能不为空,然后无条件地附加它...
let me = Contact(name: "Stefan", isFavorite: true)
let favorite = me.isFavorite ? " is a favorite contact" : ""
var message = "Contact \(me.name)\(favorite)"