[Objective-C] iOS 16 Bug in NSLocalizedString

A string created from NSLocalizedString is an instance of _NSBPlistMappedString, which might cause an incorrect result of comparing 2 strings

Penny Ng
2 min readNov 1, 2022

There are 2 strings: one is created from NSLocalizedStringand the other is passed from Swift. The result of comparing if 2 strings are equal is supposed to be YES, but it turns out to be NO.

BOOL isEqual = [swiftString isEqualToString: localizedString];

It is because, in iOS 16, a string created from NSLocalizedString in Objective-C is an instance of _NSBPlistMappedString, which is an undocumented subclass of NSString.

Comparing a Swift string with a string of that subclass using isEqualToString: causes an incorrect result if isEqualToString: is called on the Swift string.

BOOL isEqual = [swiftString isEqualToString: localizedString];  
// NO

However, the comparison generates a correct result if isEqualToString: is called on a string created from NSLocalizedString string.

BOOL isEqual = [localizedString isEqualToString: swiftString];  
// YES

Comparison between an NSString instance and a NSLocalizedString string is correct as well.

There are 2 workarounds:

  1. call isEqualToString: on the NSLocalizedString string
  2. make sure the NSLocalizedString string is an instance of NSString before the comparison

--

--

Penny Ng

A passionate self-taught  iOS developer. Write to record my learning and share the knowledge