如何使用格式创建一个字符串?

245

我需要创建一个格式化的字符串,可以将IntInt64Double等类型转换成String。在使用Objective-C时,我可以这样做:

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

如何在Swift中执行相同的操作?

15个回答

462

我想这可能会对你有所帮助:

import Foundation

let timeNow = time(nil)
let aStr = String(format: "%@%x", "timeNow in hex: ", timeNow)
print(aStr)

例子结果:

timeNow in hex: 5cdc9c8d

1
非常棒的答案!这绝对是正确的方法。对于其他人,需要注意的是,类方法“stringWithFormat”会被转换为类的init调用,并将“WithFormat”转换为名为“format:”的第一个参数。原始问题没有添加任何特定的格式,比如更改要显示的浮点小数的数量,如果他添加了,那么你的回答就是唯一的! - David H
4
您需要文档链接吗?我正在努力寻找它。 - dumbledad
6
这个方法来自于 Foundation 框架中的 NSString。因此,您需要 import Foundation 以使其正常工作。否则,该表达式将调用 String.init<T>(T),并且它会产生类似于 "(\"%@%x %x\", 10)" 的东西。 - eonil
1
@realityone,"%@%x"符号是什么意思?您能指导我一些可以了解更多的资源吗? - bibscy
8
这是一篇关于Cocoa字符串格式说明符的官方文档,涵盖了在字符串中使用格式说明符的基础知识和语法。该文档详细介绍了各种格式说明符的类型和用法,包括字符串、数字、日期和时间等类型的格式化。此外,还提供了示例代码和实用技巧,帮助开发人员更好地理解和应用格式说明符。 - realityone

126

没有特别之处

let str = NSString(format:"%d , %f, %ld, %@", INT_VALUE, FLOAT_VALUE, LONG_VALUE, STRING_VALUE)

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

更新:我在Swift的API中加入String(format:)方法之前写了这个答案。请使用最佳答案中提供的方法。


6
我认为这并没有回答问题,因为没有格式。使用这种方法,您无法格式化浮点数中要有多少位小数。使用 String(format:arguments:) 更适合添加格式。 - Chris
5
楼主并没有要求任何格式化,只是需要一种方法来创建一个带有格式的字符串,可以将int、long、double等类型转换为字符串 - John Estropia
问题不太清楚。因为他正在比较他想要的 -stringWithFormat: 和允许格式化的内容。在 Swift 中,String(format:arguments:) 将是 Obj-C 的 -stringWithFormat: 的 Swift 版本。 - Chris
请检查问题的日期。这是在Swift首次发布时,NSString方法尚未在Swift的String中实现。 - John Estropia
我改正了。将新的方法展示给未来搜索同样问题的人仍然是有益的。 - Chris

53

无需 NSString

String(format: "Value: %3.2f\tResult: %3.2f", arguments: [2.7, 99.8])
或者
String(format:"Value: %3.2f\tResult: %3.2f", 2.7, 99.8)

16

我认为两者都有道理。

let str = String(format:"%d, %f, %ld", INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE)

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

两种方式都可以接受,因为用户询问了格式,两种情况都符合他们所要求的:

 

我需要创建一个格式化字符串,可以将 int、long、double 等类型转换为字符串。

显然前一种方式比后一种方式有更精细的控制,但这并不意味着后者不是一个可接受的答案。


STRING_VALUE是什么:在Swift字符串中应该使用哪个格式符号,是否与NSString-s的情况相同(即%@)? - Igor Vasilev

6

首先阅读Swift语言的官方文档

答案应该是

var str = "\(INT_VALUE) , \(FLOAT_VALUE) , \(DOUBLE_VALUE), \(STRING_VALUE)"
println(str)

在这里:

1)默认情况下,任何浮点数值都是 double 类型。

EX.
 var myVal = 5.2 // its double by default;

-> 如果您想显示浮点数值,则需要显式定义,例如:

 EX.
     var myVal:Float = 5.2 // now its float value;

这更加清晰易懂。

4
let INT_VALUE=80
let FLOAT_VALUE:Double= 80.9999
let doubleValue=65.0
let DOUBLE_VALUE:Double= 65.56
let STRING_VALUE="Hello"

let str = NSString(format:"%d , %f, %ld, %@", INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, STRING_VALUE);
 println(str);

2
我们可以不使用修饰词,这是正确的,但代码会很长。 - Gaurav Gilani

3

接受的答案绝对是关于这个问题的最佳通用解决方案(即只需使用“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引入的,因此请务必阅读原始提案以更深入地了解这个新功能。最后,协议文档也很有帮助。


1

如果您不能导入Foundation,使用round()和/或不想要一个String,我学习了一种简单的解决方案,“我们<3 Swift”。

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

结果:31.726

1

我知道这篇文章已经发布很久了,但是我遇到了类似的情况,并创建了一个简单的类来简化我的生活。

public struct StringMaskFormatter {

    public var pattern              : String    = ""
    public var replecementChar      : Character = "*"
    public var allowNumbers         : Bool      = true
    public var allowText            : Bool      = false


    public init(pattern:String, replecementChar:Character="*", allowNumbers:Bool=true, allowText:Bool=true)
    {
        self.pattern            = pattern
        self.replecementChar    = replecementChar
        self.allowNumbers       = allowNumbers
        self.allowText          = allowText
    }


    private func prepareString(string:String) -> String {

        var charSet : NSCharacterSet!

        if allowText && allowNumbers {
            charSet = NSCharacterSet.alphanumericCharacterSet().invertedSet
        }
        else if allowText {
            charSet = NSCharacterSet.letterCharacterSet().invertedSet
        }
        else if allowNumbers {
            charSet = NSCharacterSet.decimalDigitCharacterSet().invertedSet
        }

        let result = string.componentsSeparatedByCharactersInSet(charSet)
        return result.joinWithSeparator("")
    }

    public func createFormattedStringFrom(text:String) -> String
    {
        var resultString = ""
        if text.characters.count > 0 && pattern.characters.count > 0
        {

            var finalText   = ""
            var stop        = false
            let tempString  = prepareString(text)

            var formatIndex = pattern.startIndex
            var tempIndex   = tempString.startIndex

            while !stop
            {
                let formattingPatternRange = formatIndex ..< formatIndex.advancedBy(1)

                if pattern.substringWithRange(formattingPatternRange) != String(replecementChar) {
                    finalText = finalText.stringByAppendingString(pattern.substringWithRange(formattingPatternRange))
                }
                else if tempString.characters.count > 0 {
                    let pureStringRange = tempIndex ..< tempIndex.advancedBy(1)
                    finalText = finalText.stringByAppendingString(tempString.substringWithRange(pureStringRange))
                    tempIndex = tempIndex.advancedBy(1)
                }

                formatIndex = formatIndex.advancedBy(1)

                if formatIndex >= pattern.endIndex || tempIndex >= tempString.endIndex {
                    stop = true
                }

                resultString = finalText

            }
        }

        return resultString
    }

}

以下链接为完整源代码: https://gist.github.com/dedeexe/d9a43894081317e7c418b96d1d081b25

该解决方案基于以下文章: http://vojtastavik.com/2015/03/29/real-time-formatting-in-uitextfield-swift-basics/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接