Search code examples
iosswiftstringexc-bad-access

Why do I get EXC_BAD_ACCESS when using %1$s for String(format:)


I have a localized string that looks like this:

String(format: "unable_to_reach".localized(), name) //name is a string. I have also tried just "x"

The key/value pair in the localize file looks like this:

"unable_to_reach" = "Unable to reach %1$s";

Now, sometimes this works, othertimes it crashes with the EXC_BAD_ACCESS error. Why is this? isn't %1$s supposed to be used for string values?


Solution

  • The format specifier %1$s is %s with a positional specifier of $1 inserted into it. %s is the format specifier for a null-terminated C string. If you instead pass it a Swift String, bad things will happen. Don't do that. (It will likely cause a buffer overflow if the Swift string does not contain any null bytes.)

    You want %@ (or %$1@, to preserve the positional specifier.)

    See the document on string format specifiers for more information.

    Edit:

    BTW, you should think about using Swift string interpolation instead:

    let unableToReach = "unable_to_reach".localized()
    let final = "\(unableToReach) \(name)"
    

    That is more "Swifty".

    Note that if you want to use localized placeholders to allow for different word ordering in different languages, you really still need to use String(format:) and the %@ (or %1@ positional syntax) version.