更新:奇怪的是,setlocale()仅在iOS模拟器上失败,因此我修改了问题标题。它在实际设备上运行良好。
我在iOS 6下使用本机(C / C ++)代码,我需要格式化任意wchar_t
字符串。但是,在格式化包含Latin-1代码页之外的代码点的字符串时,swprintf
会失败(返回值为-1且errno = EILSEQ
)。
wchar_t buff[256];
swprintf(buff, 256, L"\u00A9 %ls", L"ascii"); // works
swprintf(buff, 256, L"\u03A0 %ls", L"ascii"); // will return -1
在询问相关问题here后,问题似乎是未正确设置区域设置(我已验证该解决方案在Mac OS X下运行)。但它似乎在iOS 6下没有效果:
#include <locale.h>
setlocale(LC_CTYPE,"");
按照说明here,我已手动将区域设置文件复制/添加到我的项目中,并设置PATH_LOCALE
环境变量,但问题仍然存在:
NSString* resourcePath=[[NSBundle mainBundle] resourcePath];
setenv("PATH_LOCALE", [resourcePath UTF8String], 1);
setlocale(LC_CTYPE,"en_US.UTF-8");
有没有人知道如何让setlocale()在iOS 6下工作(同时Apple Store仍然接受该应用程序)?
答案 0 :(得分:0)
PATH_LOCALE是语言环境文件的基本路径,每个语言环境都位于子目录中,例如:
fr / LC_TIME fr / .. zh / LC ...
因此您需要子目录,而iOS捆绑软件不支持子目录。
这样做的时候
setlocale(LC_CTYPE,“ en_US.UTF-8”);
C库在PATH_LOCALE中查找名为“ en_US.UTF-8”的目录。
我找到的解决方案是将捆绑软件中的语言环境添加为zip文件(具有整个子目录结构),在首次启动时将其解压缩到文档路径中,然后将PATH_LOCALE设置为该新目录。
NSString* documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString* localeDir = [documentsPath stringByAppendingPathComponent:@"/locale"];
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:localeDir];
if (!fileExists) {
NSString *filepath = [[NSBundle mainBundle] pathForResource:@"locale" ofType:@"zip"];
ZipArchive *zipArchive = [[ZipArchive alloc] init];
[zipArchive UnzipOpenFile:filepath];
[zipArchive UnzipFileTo:documentsPath overWrite:YES];
[zipArchive UnzipCloseFile];
}
setenv("PATH_LOCALE", [[NSString stringWithFormat:@"%@/locale", documentsPath] cString], 1);
这使用了必须包含在项目中的Ziparchive。
答案 1 :(得分:0)
我无法获得斯蒂芬的解决方案。但是,这两个超级简单的解决方案都对我有用:
setlocale(LC_CTYPE, "UTF-8")
newlocale(LC_CTYPE_MASK, "UTF-8")
与带有语言环境参数的foo_l变体wchar_t类组合。尽管iOS可能未附带完整的语言环境套件(包括en_US.UTF-8),但它似乎附带了无语言的基本UTF-8。但它仅适用于LC_CTYPE;尝试LC_ALL将失败。您当然可以使用
进行测试char *result = setlocale(LC_TYPE, "UTF-8");
Assert(result && strcmp(result, "UTF-8") == 0);