CFLocaleCopyCurrent stale value

安稳与你 提交于 2019-12-11 14:46:14

问题


At my workplace, our app determines the locale of the user session by using a code that is similar to below (though there are various layers of code it passes through before it reaches here at the time of startup, so the problem is/may not evident by running the code below)

#include <CoreFoundation/CoreFoundation.h>  
#include <iostream>  
#include <string>  
#include <vector>  
#include <memory>  

  // Reference release  
    struct reference_close  
    {  
        void operator()(const void *ref) const  
        {  
            CFRelease(static_cast<CFTypeRef>(ref));  
        }  
    }; // end of reference_close structure  

    typedef std::unique_ptr<const void, reference_close>  reference_uptr;  

    std::string get_user_locale()  
    {  
        reference_uptr  ref_ptr(CFLocaleCopyCurrent());  
        CFLocaleRef    locale_ref(static_cast<CFLocaleRef>(ref_ptr.get()));  
        if (locale_ref == nullptr)  
        {  
            return std::string();  
        }  
        const size_t      default_size(128);  
        std::vector<char>  buff(default_size);  
        CFStringRef        str_ref(CFLocaleGetIdentifier(locale_ref));  

      if (str_ref != nullptr)  
        {  
            CFIndex  len(CFStringGetLength(str_ref) + 1);  
            if (len > boost::numeric_cast<CFIndex>(default_size))  
            {  
                buff.resize(len);  
            }  

            buff[0] = 0;  
            if (!CFStringGetCString(str_ref, &buff[0], len, kCFStringEncodingISOLatin1))  
            {  
                return std::string();  
            }  
        }  

        return std::string(&buff[0]);  
    } // end of get_user_locale()  

int main()  
{  
    std::cout << "get_user_locale() : "<<get_user_locale() << std::endl;  

    return 0;  
}  

The app has a well defined bundle structure with necessary resources and localization resource directories e.g Contents/Resources/ja.lproj

Lately, we are facing an issue wherein we do the following

1) Change the system language and country in the preferences e.g. change from en_US to ja_JP

2) Reboot the machine

3) Launch the app and see the erroneous output e.g en_JP

4) Re-launch the app to get the correct answer as ja_JP

I have read the documentation of CFLocaleCopyCurrent which states that

Settings you get from this locale do not change as a user's preferences are changed so that your operations are consistent. Typically you perform some operations on the returned object and then release it. Since the returned object may be cached, you do not need to hold on to it indefinitely.

I also checked the another documentation on lifetime of CFLocale which states that

The object you get back from CFLocaleCopyCurrent does not change when the user changes their Preferences settings. Moreover, the object itself may be cached by the runtime system, so successive calls of CFLocaleCopyCurrent may return the same object, even if a user has changed preference settings. If you want to ensure that your locale settings are consistent with user preferences, you must synchronize preferences and get a new locale object with CFLocaleCopyCurrent.

Given this info, I tried to incorporate CFPreferencesSynchronize and/or CFPreferencesSynchronize in the app code (just before I call the CFLocaleCopyCurrent) to get the most updated locale. But no luck.

Do I need to do anything extra to make sure that I get the most recent/updated value of locale object from the system preferences ?


回答1:


Use [NSLocale autoupdatingCurrentLocale] which will change as the user changes their locale settings, but as NSLocale is an Objective-C class you will need to implement glue code as Objective-C++.

Here is some untested example code, giving you the idea:

Create a file called AppleLocale.mm (unless of course your project is for Apple platforms only so doesn't need the Apple name prefix).

#include <Foundation/Foundation.h>

std::string get_user_locale()
{
    NSLocale* locale = [NSLocale autoupdatingCurrentLocale];
    return std::string([[locale localeIdentifier] UTF8String]);
}

Note: You'll need a function prototype in some header as well, of course.



来源:https://stackoverflow.com/questions/58713505/cflocalecopycurrent-stale-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!