格式化 Swift 中的字符串

Formatting strings in Swift

在某些语言中,例如 C#,您可以通过以下方式创建字符串:

"String {0} formatted {1} "

然后通过传入要格式化的值,使用 String.format 对其进行格式化。

上面的声明很好,因为你在创建字符串的时候不需要知道它的参数是什么类型。

我试图在 Swift 中找到类似的方法,但我发现的是类似于以下格式的内容:

"String %d formatted %d"

这需要您使用 String(format: , parameters) 格式化字符串。这不好,因为在声明字符串时您还必须知道参数类型。

在 Swift 中是否有类似的方法,我不必知道参数类型?

在 Swift 中,类型需要符合 CustomStringConvertible protocol 才能在字符串中使用。这也是字符串插值中使用的类型的要求,如下所示:

"Integer value \(intVal) and double value \(doubleVal)"

了解 CustomStringConvertible 后,您可以创建自己的函数来满足您的需求。以下函数根据给定的参数格式化字符串并打印它。它使用 {} 作为参数的占位符,但您可以将其更改为您想要的任何内容。

func printWithArgs(string: String, argumentPlaceHolder: String = "{}", args: CustomStringConvertible...) {
    var formattedString = string
    
    // Get the index of the first argument placeholder
    var nextPlaceholderIndex = string.range(of: argumentPlaceHolder)
    
    // Index of the next argument to use
    var nextArgIndex = 0

    // Keep replacing the next placeholder as long as there's more placeholders and more unused arguments
    while nextPlaceholderIndex != nil && nextArgIndex < args.count {
        
        // Replace the argument placeholder with the argument
        formattedString = formattedString.replacingOccurrences(of: argumentPlaceHolder, with: args[nextArgIndex].description, options: .caseInsensitive, range: nextPlaceholderIndex)
        
        // Get the next argument placeholder index
        nextPlaceholderIndex = formattedString.range(of: argumentPlaceHolder)
        nextArgIndex += 1
    }
    
    print(formattedString)
}

printWithArgs(string: "First arg: {}, second arg: {}, third arg: {}", args: "foo", 4.12, 100)
// Prints: First arg: foo, second arg: 4.12, third arg: 100

使用自定义实现可以让您更好地控制它并调整它的行为。例如,如果您愿意,可以修改此代码以显示相同的参数多次使用 {1}{2} 等占位符,您可以按相反的顺序填写参数等

有关 Swift 中字符串插值的更多信息:https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-ID292

使用这个:

let printfOutput = String(format:"%@ %2.2d", "string", 2)

它与 printf 或 Obj-C 格式相同。

你也可以这样搭配:

let parm = "string"
let printfOutput = String(format:"\(parm) %2.2d", 2)

编辑:感谢 MartinR(他无所不知 ;-)

Be careful when mixing string interpolation and formatting. String(format:"\(parm) %2.2d", 2) will crash if parm contains a percent character. In (Objective-)C, the clang compiler will warn you if a format string is not a string literal.

这为黑客攻击提供了一些空间:

let format = "%@"
let data = "String"
let s = String(format: "\(format)", data) // prints "String"

与在编译时解析格式字符串的 Obj-C 相比,Swift 不这样做,只是在运行时解释它。