Reputation: 1455
Using Swift 3, deployment target iOS 9 or 10. Tested this on both.
Why does:
let s = "8 août 2017"
let sUtf8 = (s as NSString).utf8String!
let template = "%1$s"
let s1 = String(format: template, arguments: [sUtf8])
NSLog(s1)
let s2 = String.localizedStringWithFormat(template,((s as NSString).utf8String)!)
NSLog(s2)
log "8 ao√ªt 2017" instead of "8 août 2017"?
Upvotes: 0
Views: 113
Reputation: 47896
Please check the Apple's documentation of String Format Specifiers.
%s
Null-terminated array of 8-bit unsigned characters. Because the%s
specifier causes the characters to be interpreted in the system default encoding, the results can be variable, especially with right-to-left languages. For example, with RTL,%s
inserts direction markers when the characters are not strongly directional. For this reason, it’s best to avoid %s and specify encodings explicitly.
(Bold style added.)
There's no guarantee that the passed byte sequence is interpreted as UTF-8.
The UTF-8 byte sequence for "8 août 2017"
(in hexadecimal):
38 20 61 6f c3 bb 74 20 32 30 31 37
If your device's default encoding is set to ISO-Latin1, the bytes are interpreted as:
(The system default encodings may be different in users' devices.)
8 a o √ ª t 2 0 1 7
Generally useful guideline: Never use %s
in your Swift code.
In Swift code, use %@
instead. (I recommend to use %@
in Objective-C as far as possible.)
let s = "8 août 2017"
let template = "%1$@"
let s1 = String(format: template, s)
NSLog(s1) //->8 août 2017
let s2 = String.localizedStringWithFormat(template, s)
NSLog(s2) //->8 août 2017
You have no need to use ugly and risky(*) (s as NSString).utf8String
.
(*) The lifetime of C-string region for .utf8String
may be shorter than the string object. And, in Swift, the lifetime of the string object may be far shorter than that in Objective-C.
Upvotes: 2