1

I want to format a string, in Swift, with two potential arguments (using Format specifiers). The string to format may have a place for only the first argument, only the second argument, or both arguments. If I use the first or both arguments it works, but if I use only the second argument, it does not work. For instance:

let title = "M."
let name = "David"
let greetingFormat = "Hello %1$@ %2$@"
print(String(format: greetingFormat, title, name))
// OUTPUT> Hello M. David
// OK

If I use only the first argument in the String to format:

let greetingFormat = "Hello %1$@"
print(String(format: greetingFormat, title, name))
// OUTPUT> Hello M.
// OK

But when using only the second argument

let greetingFormat = "Hello %2$@"
print(String(format: greetingFormat, title, name))
// OUTPUT> Hello M.
// NOT THE EXPECTED RESULT!

In the last case I expected "Hello David". Is it a bug? How can I obtain the intended result for the last case where only the second argument is used?

Remarks:

  • Please note that this problem occurs in the context of localization (i.e. the string to format comes from a Localizable.strings file), so I don’t have the possibility to remove unused argument directly.
  • The question does not relate to person’s name formatting. This is just taken as a example.
David
  • 31
  • 5
  • https://stackoverflow.com/a/27870553/2303865 – Leo Dabus May 08 '20 at 13:19
  • 2
    Indeed `String(format:)` does not support omitting positional parameters. – According to https://stackoverflow.com/a/2946880/1187415, this is *not* a bug. – Martin R May 08 '20 at 13:24
  • Thanks [Martin R](https://stackoverflow.com/users/1187415/martin-r). I created an answer based on your comment but feel free to create your answer and I will mark it as accepted to credit you. – David May 08 '20 at 19:19

1 Answers1

1

I answer my own question but all credit to @Martin R that provides the relevant information in comments.

  • It is not a bug, String(format:) does not support omitting positional parameters.
  • It is a known behavior since ObjectiveC, see: stackoverflow.com/a/2946880/1187415
  • If you only have String arguments you can use multiple String substitutions with String.replacingOccurrences(of:, with:) instead of String(format:).

More precision on the last solution. The following will work in the case that only one argument is used and also if both arguments are used in the greetingFormat String:

greetingFormat.replacingOccurrences(
    of: "%1$@", with: title)
    .replacingOccurrences(
    of: "%2$@", with: name)

Of course, with String.replacingOccurrences(of:, with:) you can choose other identifiers for the substitution than %1$@ and %2$@.

David
  • 31
  • 5