在Swift中使用%@格式化字符串

18

我有一个包含私有结构体字符串的类,我希望以后可以将它们用于格式化字符串。然而,在运行时代码崩溃了。

为什么会这样?是因为它被定义为静态let吗?

下面是精简后的代码:

class LGNotificationHandler {
    private struct Strings {
        static let SentImagesENG = "Sent %@ images to the event"
        static let SentImagesTUR = "Etkinliğe %@ görsel gönderdi"
    }

    func buildNotificationString(imageCount: Int) -> String {
        if imageCount == 1 {
        .
        .
        .

        } else {
            // below line is giving error at run time
            notificationENG = String(format: Strings.SentImagesENG, imageCount)  
            notificationTUR = String(format: Strings.SentImagesTUR, imageCount)  
        }
    }
}

哪一行导致了崩溃?崩溃时的错误信息是什么? - rmaddy
notificationENG = 'the line starting with ' gives error. I mention this in the comment at the end of the line. I will put it above the line for better visibility. The error I get is Thread 20: EXC_BAD_ACCESS (code=1, address=0x2)'。 - oyalhi
3个回答

22

您没有提供有关崩溃的任何详细信息,但一个明显的问题是在使用 Int 时使用了 %@ 格式说明符。您需要使用 %d


2
实际上,%@ 是用于对象的,而不仅仅是文本。您可以在文档中找到有关所有格式说明符的详细信息。查看 NSString stringWithFormat: 的文档以获取链接。 - rmaddy
3
实际上,这是链接:https://developer.apple.com/library/prerelease/content/documentation/CoreFoundation/Conceptual/CFStrings/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265 - rmaddy

20

您需要将%@替换为%d。ImageCount是Int值。因此请使用%d,而不是%@

格式说明符:

%d - int Value 
%f - float value
%ld - long value
%@ - string value and for many more.

请查看苹果官方文档 格式说明符 以查看所有格式说明符。


9

更新 简化版本

extension String {

    func format(_ arguments: CVarArg...) -> String {
        let args = arguments.map { String(describing: $0) } as [CVarArg]
        return String.init(format: self, arguments: args)
    }

}

您可以使用此扩展

Swift 5

extension String {

    func format(_ arguments: CVarArg...) -> String {
        let args = arguments.map {
            if let arg = $0 as? Int { return String(arg) }
            if let arg = $0 as? Float { return String(arg) }
            if let arg = $0 as? Double { return String(arg) }
            if let arg = $0 as? Int64 { return String(arg) }
            if let arg = $0 as? String { return String(arg) }
            if let arg = $0 as? Character { return String(arg) }

            return "(null)"
        } as [CVarArg]

        return String.init(format: self, arguments: args)
    }

}

使用:

let txt = "My name is %@, I am %@ years old".format("Mickael", 24)

将'CVarArg'从强制转换为不相关的类型'Character'始终失败。 - Ahmadreza
强制将每种数据类型都转换为字符串,以便格式化字符串只能使用“%@”是没有意义的。这样会失去所有格式说明符的功能。如果我想要将Double格式化为3位小数怎么办?如果我想要将Int强制转换为2位数字,并在需要时添加前导0怎么办?此外,如果我传入一个使用除“%@”之外的格式说明符的字符串,这段代码很可能会崩溃。 - HangarRash

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