在运行时更改iOS模拟器的当前区域设置 [英] Change the iOS simulator's current locale at runtime

查看:100
本文介绍了在运行时更改iOS模拟器的当前区域设置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

While developing a set of date calculations and language rules for converting numeric values and dates to strings, I'm writing tests that assert the outcome of the string formatting method. An imaginary assertion for it might looks like this:

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

但是,因为该应用程序已针对多种语言进行了本地化,而且我的开发人员也来自不同的语言语言环境比我,可能会发生您的设备或模拟器设置为与正在编写测试的语言环境不同的语言环境。在这种情况下, dateString 的内容可能类似于:

However, because the app is localized for several languages, and my fellow developers are also from and in different locales than I, it can happen that your device or simulator is set to a different locale than the one that the tests are being written for. In a scenario like this, the contents of the dateString might be something like:

@"Drie dagen, tot 18:00" // the assertion fails
@"Drei Tage, bis 18 Uhr" // the assertion also fails

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

This may or may not be the correct date notation for these locales, but the part that my question is about, is how to be able to run tests to a specific locale, when the underlying code makes use of Apple API like this:

[NSDateFormatter localizedStringFromDate:date 
                 dateStyle:NSDateFormatterNoStyle 
                 timeStyle:NSDateFormatterShortStyle];

我希望在我的断言中涵盖两种或更多种语言,例如:

I would love to cover at two or more languages in my assertions, with something like this:

[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");

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

注意:


  • 更改首选语言不会削减它,它还需要影响NSDateFormatter和NSNumberFormatter行为。

  • 因为这仅用于单元测试目的,所以我会满足于使用私有API。但是,为了其他人在这篇文章上磕磕绊绊的好处,首选公共API。

  • 将自定义区域设置传递给每个日期或数字格式API可能是最后一个考虑因素,但我发布此问题希望 避免 回归那些极端措施。如果您知道这是唯一的解决方案,请提供一些参考,我将不再浪费时间

  • Changing the preferred language does not cut it, it also needs to influence the NSDateFormatter and NSNumberFormatter behavior.
  • Because this is for unit testing purposes only, I'd be content with using private API. However, for the benefit of other people stumbling on this post, public API is preferred.
  • Passing a custom locale to each and every date or number formatting API might be a final consideration, but I'm posting this question hoping to avoid falling back to those extreme measures. If you however know this to be the only solution, please provide some reference and I'll waste no more time

关于该主题的链接:

  • Nice article by Ray Lillywhite on i18n and l10n
  • NSHipster article on NSLocale

推荐答案

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

解决方案,转out,与调整类方法在内部使用的方法一样简单:

The solution, turns out, is "as easy" as swizzling the methods that the class methods use internally:

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

afterEach(^{
    [NSLocale ttt_resetRuntimeLocale];
    [NSBundle ttt_resetLanguage];
});

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

The ttt_... methods you see above use the categories on NSObject, NSLocale and NSBundle to check at runtime whether it should use the original methods or return something else. This method works flawlessly when writing your tests, and although it doesn't technically use any private API, I would strongly suggest only to use this in your test setup, not for anything you submit to the App Store for review.

在这个要点中,你会找到我添加的Objective-C类别我的应用测试目标以达到所需的行为。

In this gist you'll find the Objective-C categories I added to my app's test target to achieve the required behavior.

这篇关于在运行时更改iOS模拟器的当前区域设置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆