Возможная ошибка iOS 16 при переходе NSLocalizedString из Swift в Objective-C
Я столкнулся с тем, что я считаю ошибкой в iOS16: когда локализованная строка передается из Swift в Objective-C и сравнивается с другой идентичной локализованной строкой (определенной в Objective-CC), результат может быть ложным, а порядок параметров может повлиять на результат. Смотрите демо:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let tc = TestClass()
tc.receive(NSLocalizedString("Start", comment:""))
}
}
@implementation TestClass
- (void)receive:(NSString *)swiftString {
NSString *objcString = NSLocalizedString(@"Start", @"");
BOOL result1 = [swiftString isEqualToString:objcString];
BOOL result2 = [objcString isEqualToString:swiftString];
NSLog(@"result: %d, %d", result1, result2);
}
@end
Его можно локализовать (в качестве примера возьмем японский, но любая система письма, кроме латиницы, может воспроизвести ошибку):
"Start" = "開始";
выход:
result: 0, 1
Мы не знаем, является ли основная причина этогоNSLocalizedString()
или-isEqualToString
. Это не происходит на iOS15.
Кто-нибудь еще сталкивался с этим багом?
1 ответ
Это определенно похоже на ошибку, я мог бы воспроизвести ее в симуляторе Xcode iOS 16. Отладчик показывает, что строка, полученная
NSString *objcString = NSLocalizedString(@"Start", @"");
является примером_NSBPlistMappedString
, недокументированный подкласс:
(lldb) p objcString
(_NSBPlistMappedString *) $1 = 0x8230ceeb696930f7
(lldb) p [objcString superclass]
(Class) $2 = NSString
По-видимому, сравнение строки Swift с экземплярами этого подкласса реализовано неправильно в iOS 16. Вот два возможных решения:
Обходной путь № 1: использованиеcompare
вместоisEqualToString
:
NSString *objcString = NSLocalizedString(@"Start", @"");
BOOL result1 = [swiftString compare:objcString] == NSOrderedSame;
BOOL result2 = [objcString compare:swiftString] == NSOrderedSame;
NSLog(@"result: %d, %d", result1, result2);
// result: 1, 1
Обходной путь № 2: убедитесь, чтоobjcString
является примеромNSString
:
NSString *objcString = @(NSLocalizedString(@"Start", @"").UTF8String);
BOOL result1 = [swiftString isEqualToString:objcString];
BOOL result2 = [objcString isEqualToString:swiftString];
NSLog(@"result: %d, %d", result1, result2);
// result: 1, 1
Конечно, оба обходных пути не очень удовлетворительны. Как было предложено в комментариях, об ошибке следует сообщить в Apple.