我需要创建一个字符串的格式,可以转换Int, Int64,双精度等类型为字符串。使用Objective-C,我可以通过:

NSString *str = [NSString stringWithFormat:@"%d , %f, %ld, %@", INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, STRING_VALUE];

如何做同样的,但在Swift?


当前回答

let str = "\(INT_VALUE), \(FLOAT_VALUE), \(DOUBLE_VALUE), \(STRING_VALUE)"

更新:在Swift将String(format:)添加到API之前,我写了这个答案。使用上面的答案给出的方法。

其他回答

公认的答案肯定是最好的通用解决方案(即,只需使用Foundation中的String(format:_:)方法),但…

如果你运行的是Swift≥5,你可以利用新的StringInterpolationProtocol协议为你的应用程序中常见的字符串格式化用例提供一些非常好的语法糖。

以下是官方文件对这项新协议的总结:

表示在构建字符串文字时进行插值的字符串文字的内容。

一些简单的例子:

extension String.StringInterpolation {

    /// Quick formatting for *floating point* values.
    mutating func appendInterpolation(float: Double, decimals: UInt = 2) {
        let floatDescription = String(format: "%.\(decimals)f%", float)
        appendLiteral(floatDescription)
    }

    /// Quick formatting for *hexadecimal* values.
    mutating func appendInterpolation(hex: Int) {
        let hexDescription = String(format: "0x%X", hex)
        appendLiteral(hexDescription)
    }

    /// Quick formatting for *percents*.
    mutating func appendInterpolation(percent: Double, decimals: UInt = 2) {
        let percentDescription = String(format: "%.\(decimals)f%%", percent * 100)
        appendLiteral(percentDescription)
    }

    /// Formats the *elapsed time* since the specified start time.
    mutating func appendInterpolation(timeSince startTime: TimeInterval, decimals: UInt = 2) {
        let elapsedTime = CACurrentMediaTime() - startTime
        let elapsedTimeDescription = String(format: "%.\(decimals)fs", elapsedTime)
        appendLiteral(elapsedTimeDescription)
    }
}

可用作:

let number = 1.2345
"Float: \(float: number)" // "Float: 1.23"
"Float: \(float: number, decimals: 1)" // "Float: 1.2"

let integer = 255
"Hex: \(hex: integer)" // "Hex: 0xFF"

let rate = 0.15
"Percent: \(percent: rate)" // "Percent: 15.00%"
"Percent: \(percent: rate, decimals: 0)" // "Percent: 15%"

let startTime = CACurrentMediaTime()
Thread.sleep(forTimeInterval: 2.8)
"∆t was \(timeSince: startTime)" // "∆t was 2.80s"
"∆t was \(timeSince: startTime, decimals: 0)" // "∆t was 3s"

这是由SE-0228引入的,所以请务必阅读原始提案,以更深入地了解这个新功能。最后,协议文档也很有帮助。

成功尝试一下:

 var letters:NSString = "abcdefghijkl"
        var strRendom = NSMutableString.stringWithCapacity(strlength)
        for var i=0; i<strlength; i++ {
            let rndString = Int(arc4random() % 12)
            //let strlk = NSString(format: <#NSString#>, <#CVarArg[]#>)
            let strlk = NSString(format: "%c", letters.characterAtIndex(rndString))
            strRendom.appendString(String(strlk))
        }

由于字符串(格式:"%s"…)在运行时崩溃,下面的代码允许编写类似"hello".center(42);“世界”.alignLeft (42):

extension String {

    // note: symbol names match to nim std/strutils lib:

    func align (_ boxsz: UInt) -> String {
        self.withCString { String(format: "%\(boxsz)s", $0) }
    }

    func alignLeft (_ boxsz: UInt) -> String {
        self.withCString { String(format: "%-\(boxsz)s", $0) }
    }

    func center (_ boxsz: UInt) -> String {
        let n = self.count
        guard boxsz > n else { return self }
        let padding = boxsz - UInt(n)
        let R = padding / 2
        guard R > 0 else { return " " + self }
        let L = (padding%2 == 0) ? R : (R+1)
        return " ".withCString { String(format: "%\(L)s\(self)%\(R)s", $0,$0) }
    }

}

有一个简单的解决方案,我学会了“我们<3 Swift”,如果你既不能导入基础,使用round()和/或不想要字符串:

var number = 31.726354765
var intNumber = Int(number * 1000.0)
var roundedNumber = Double(intNumber) / 1000.0

结果:31.726

String(format:)的美妙之处在于,你可以保存一个格式化字符串,然后在很多地方重复使用。它也可以本地化到这个地方。在插值的情况下,你必须一遍又一遍地写。