Let's assume that we can change in runtime Localizable.strings, that is placed in NSBundle At the current moment, even if we change it's contents, NSLocalizedString would return old(cached) values.

  1. Run Application
  2. Get LocalizableString for specific key1 <- value1
  3. Change Localizable.strings key1 = value2
  4. <-- Do something in application to invalidate Localization cache -->
  5. Check if LocalizableString for specific key1 == value2

What I've already tried:

  • [[NSBundble mainBundle] invalidateResourceCache]
  • [UIApplication _performMemoryWarning]
  • Tried to see, if there's some dictionaries. used for caching, in ivars in NSBundle.
  • Tried to see, in GNUStep implementation of NSBundle, but it's different from that we have in ios 6.0

What I cannot do (by definition): - I cannot swizzle [NSBundle localizableStringForKey:value:table] - I cannot change macroses - In general, I cannot affect Any Original Project code, only add something at step #4

This is only for development purposes only. So, I don't need to publish it in AppStore or something, so any private methods, or solutions are OK.

So, the question is. May be someone know the way to do it, or someone who give me another ideas how to do it? Thank you.

有帮助吗?

解决方案

NOTE: This solution uses private APIs and your app submissions to the App Store will be rejected if you use this code.

So, after some search I've found link that helped me

How to remove NSBundle cache

// First, we declare the function. Making it weak-linked 
// ensures the preference pane won't crash if the function 
// is removed from in a future version of Mac OS X.
extern void _CFBundleFlushBundleCaches(CFBundleRef bundle) 
  __attribute__((weak_import));

BOOL FlushBundleCache(NSBundle *prefBundle) {
    // Before calling the function, we need to check if it exists
    // since it was weak-linked.
    if (_CFBundleFlushBundleCaches != NULL) {
        NSLog(@"Flushing bundle cache with _CFBundleFlushBundleCaches");
        CFBundleRef cfBundle =
           CFBundleCreate(nil, (CFURLRef)[prefBundle bundleURL]);
        _CFBundleFlushBundleCaches(cfBundle);
        CFRelease(cfBundle);
        return YES; // Success
    }
    return NO; // Not available
}

After flushing bundle cache, new localizations keys are used. So now I don't need to restart my application in simulator in order to see changes in localizable strings.

其他提示

You can use the uncache solution.

use Localizable.nocache.strings in your lproj folders.

e.g. example.bundle/Resources/de.lproj/Localizable.nocache.strings

loading localized strings after getting url via FileManager.

func localizedString(key: String) -> String {
   let bundle = Bundle(url: bundleUrl)
   return bundle.localizedString(forKey: key, value: nil, table: "Localizable.nocache")
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top