在运行时更改iOS模拟器的当前区域设置

epo*_*gee 13 cocoa-touch localization objective-c internationalization ios

在开发一组用于将数值和日期转换为字符串的日期计算和语言规则时,我正在编写断言字符串格式化方法结果的测试.对它的想象断言可能如下所示:

NSAssert([dateString isEqualToString:@"Three days, until 6:00 PM"], @"Date string should match expectation");
Run Code Online (Sandbox Code Playgroud)

但是,由于应用程序已针对多种语言进行本地化,并且我的开发人员也来自不同的语言环境,因此可能会将您的设备或模拟器设置为与为其编写测试的语言环境不同的语言环境.在这样的场景中,dateString可能是这样的内容:

@"Drie dagen, tot 18:00" // the assertion fails
@"Drei Tage, bis 18 Uhr" // the assertion also fails
Run Code Online (Sandbox Code Playgroud)

这可能是也可能不是这些语言环境的正确日期符号,但我的问题所在的部分是,当底层代码使用Apple API时,如何能够运行测试到特定的语言环境:

[NSDateFormatter localizedStringFromDate:date 
                 dateStyle:NSDateFormatterNoStyle 
                 timeStyle:NSDateFormatterShortStyle];
Run Code Online (Sandbox Code Playgroud)

我想在我的断言中用两种或更多种语言覆盖,例如:

[NSSomething actionToSetTheLocaleTo:@"en_US"];
dateString = ...; // the formatting
NSAssert([dateString isEqualToString:@"Three days, until 6:00 PM"], @"match en_US");

[NSSomething actionToSetTheLocaleTo:@"nl_NL"];
dateString = ...; // the formatting
NSAssert([dateString isEqualToString:@"Drie dagen, tot 18:00"], @"match nl_NL");
Run Code Online (Sandbox Code Playgroud)

谁知道如何实现这种效果?

笔记:

  • 更改首选语言不会削减它,它还需要影响NSDateFormatter和NSNumberFormatter行为.
  • 因为这仅用于单元测试目的,所以我会满足于使用私有API.但是,为了其他人在这篇文章上磕磕绊绊的好处,首选公共API.
  • 将自定义区域设置传递给每个日期或数字格式API可能是最后的考虑因素,但我发布此问题希望避免回到这些极端措施.如果您知道这是唯一的解决方案,请提供一些参考,我将不再浪费时间

关于这个主题的链接:

epo*_*gee 19

@Desmond指出了一个有效的解决方案.直到他在这里给出答案来提供这些信息,让我总结一下我最后用一些代码做的事情.

事实证明,解决方案"与调整类方法在内部使用的方法一样容易" :

beforeEach(^{
    [NSBundle ttt_overrideLanguage:@"nl"];
    [NSLocale ttt_overrideRuntimeLocale:[NSLocale localeWithLocaleIdentifier:@"nl_NL"]];
});

afterEach(^{
    [NSLocale ttt_resetRuntimeLocale];
    [NSBundle ttt_resetLanguage];
});
Run Code Online (Sandbox Code Playgroud)

ttt_...您在上面看到的方法使用NSObject,NSLocale和NSBundle上的类别来在运行时检查它是应该使用原始方法还是返回其他方法.这种方法在编写测试时运行完美,虽然它在技术上并不使用任何私有API,但我强烈建议只在测试设置中使用它,而不是在提交给App Store进行审查的任何内容.

在这个要点中,您将找到我添加到应用程序测试目标中的Objective-C类别,以实现所需的行为.