The peculiar case of NSString bridged strings

Found an interesting peculiarity in Strings bridged from NSString. In the following fragment I run the app and use the same string for string2 variable as the string1 obtained from the stringsdict file:

    let string1: String = NSLocalizedString("fileCountString", comment: "")
    let string2: String = "You have %#@X@"
    print(string1) // "You have %#@X@"
    print(string2) // "You have %#@X@"
    assert(string1 == string2) // โœ… OK

This fragment runs ok and the two strings are obviously equal. So far so good. Now to the odd part:

    let converted1: String = String.localizedStringWithFormat(string1, 1)
    let converted2: String = String.localizedStringWithFormat(string2, 1)
    print(converted1) // "You have 1 file"
    print(converted2) // "You have %#@X@"
    assert(converted1 == converted2) // ๐Ÿ›‘ fails obviously

The two "equal" strings passed to localizedStringWithFormat give two different results. Feels like magic. Or it's just localizedStringWithFormat implementation compares string references instead of calling isEqual.

Interestingly the third string created from the first:

let string3 = NSString(string: string1) as String

also equal to the other two strings and behaves like string2 (becomes nonlocalizable).

Should be fixed in [5.7] Handle long tagged NSStrings by Catfish-Man ยท Pull Request #60477 ยท apple/swift ยท GitHub

1 Like