问题
I'm working on an app that has a toggle button to switch between English and Arabic language and should be on the fly. I'm using the method in https://github.com/maximbilan/ios_language_manager and it works fine in all cases except if the storyboard is localized by interface not strings:
Now when I reload the root view controller like this:
func reloadRootVC(){
let delegate : AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
delegate.window?.rootViewController = (storyboard.instantiateInitialViewController())
}
it reload the root with localized strings and in RTL but with the english storyboard not the arabic one.
Tried force loading the arabic one like this:
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle(path: NSBundle.mainBundle().pathForResource(LanguageManager.currentLanguageCode(), ofType: "lproj")!))
but unfortunately it loads the storyboard but with no images. It can't read any resource image.
回答1:
I ended up by moving the arabic storyboard outside and name it Main-AR, then adding an extension in UIStoryboard to swizzle and initializer of storyboard to add -AR to the end of the storyboard name if i'm on arabic mode.
extension UIStoryboard {
public override class func initialize() {
struct Static {
static var token: dispatch_once_t = 0
}
// make sure this isn't a subclass
if self !== UIStoryboard.self {
return
}
dispatch_once(&Static.token) {
let originalSelector = #selector(UIStoryboard.init(name:bundle:))
let swizzledSelector = #selector(UIStoryboard.initWithLoc(_:bundle:))
let originalMethod = class_getClassMethod(self, originalSelector)
let swizzledMethod = class_getClassMethod(self, swizzledSelector)
class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
// MARK: - Method Swizzling
class func initWithLoc(name: String, bundle storyboardBundleOrNil: NSBundle?) -> UIStoryboard{
var newName = name
if LanguageManager.isCurrentLanguageRTL(){
newName += "-AR"
if #available(iOS 9.0, *) {
UIView.appearance().semanticContentAttribute = .ForceRightToLeft
} else {
// Fallback on earlier versions
}
}
else{
if #available(iOS 9.0, *) {
UIView.appearance().semanticContentAttribute = .ForceLeftToRight
} else {
// Fallback on earlier versions
}
}
return initWithLoc(newName, bundle: storyboardBundleOrNil)
}
}
回答2:
change the bundle which is used to init the storyboard:
let path = Bundle.main.path(forResource: "ar", ofType: "lproj")
let bundle = Bundle(path: path!)
let delegate : AppDelegate = UIApplication.shared.delegate as! AppDelegate
let storyboard = UIStoryboard(name: "Main", bundle: bundle)
delegate.window?.rootViewController = (storyboard.instantiateInitialViewController())
although this change the storyboard based on language but do not load images! :(
来源:https://stackoverflow.com/questions/37005398/localization-on-the-fly-with-localized-storyboards