How are XIBs loaded for localized apps?
I found after a couple of days of successfully running and debugging localized apps on the Simulator it (or the XCode deployment process) got into a state where, if the Simulator was set to one of my supported local languages, it would crash on startup with the following stack:
3 CoreFoundation 0x01780e6a +[NSException raise:format:] + 58
4 UIKit 0x008050fa -[UINib instantiateWithOwner:options:] + 2024
5 UIKit 0x00806ab7 -[NSBundle(UINSBundleAdditions) loadNibNamed:owner:options:] + 168
6 UIKit 0x0060c17a -[UIApplication _loadMainNibFile] + 172
7 UIKit 0x0060ccf4 -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] +
8 UIKit 0x00617617 -[UIApplication handleEvent:withNewEvent:] + 1533
9 UIKit 0x0060fabf -[UIApplication sendEvent:] + 71
10 UIKit 0x00614f2e _UIApplicationHandleEvent + 7576
11 GraphicsServices 0x01e13992 PurpleEventCallback + 1550
The crash is happening because the UIApplication is failing to load the MainWindow.nib file:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle /.app> (loaded)' with name 'MainWindow''
When you localize an app you have a couple of options. You can do one (or both) of the following:
- Localize each Xib file which gets loaded based on the language on the device. So your localized UI is completely configured from Interface Builder.
- You can set up a Localizable.strings file for each language target and access the strings therein from code.
I chose the later because I wanted all my localized strings in single place (so it can be translated all at once). What this means is that I don't have any xib files in language specific directories in my project (fr.lproj, zh-Hant.lproj etc...). Instead I have en.lproj full of all my xib files (nib files once they are built) and language specific directories containing the corresponding translated Localizable.strings files.
As I mentioned, this has been working fine for a couple of days. Today (and I am not sure at exactly what point), the App on the Simulator started crashing on startup. Installing the App on the device worked fine and running the App on the Simulator in English mode worked fine.
After a great deal of stuffing around, I realised that the 开发者_运维问答Simulator was crashing because it was looking for its nib files in the language specific directory (fr.lpro, sz-Hant.lproj, ja.lproj depending on the language settings).
So it seems like the Simulator is in a state where it isn't looking the default language directory (en.lproj) after it fails to find the nib in the language specific directory.
I worked around the problem by going into the application directory for the simulator (based on the exception message above):
/Users/.../Library/Application Support/iPhone Simulator/4.3/Applications//.app
Then going into the language specific subdirectory and copying all the nib files from en.lproj into that directory.
Having copied the files by hand, the simulator loads the language specific nib files (which are actually just copies of the files in the en.lproj directory) and everything works fine.
So my questions:
- Is this just a bug in the Simulator? So a big NO to that
- Has anyone else had this problem? Yep
- Is this a result of some obscure XCode setting that I have accidentally toggled? Nope, doesn't look like it
Update
Discovered today that this issue not confined to the simulator, this happens on the device. So the workaround I described above (copying the nibs from the default language directory to the target language directory), obviously doesn't work on the phone.
I tried McCygnus's suggested fix (remove all localizations for my xibs, which moves them back into the root directory) and that sorted it for me. So I guess the localization system checks the current language directory and then the root, it won't fall back to your default language.
I had this issue recently when I had a english version of the nib but didn't localize it for any of the other languages (MyNib was in en.lproj). The simulator was only looking in the other language directory (da.lproj, de.lproj, etc.) for MyNib and not falling back to the english version if not found. I fixed it by removing the english localization for the nib. That caused it to be the in the app bundle's root with the other resources instead of in en.lproj. After that everything worked perfectly.
I was a bit confused by it since I thought the localization system checked through all of the languages in the user's preferred order with english usually being used by the dev as the catch all. I'm not sure if this is a change in loading behavior or a simulator bug (I never tried on device). I'm guessing it's the latter, but I don't know for sure. This reminds me though that I need to submit a bug report on it.
if you are using
[[Class alloc] initWithNibName:@"aNibName" bundle:nil];
change it to
[[Class alloc] initWithNibName:@"aNibName" bundle:[NSBundle mainBundle]];
Had the same symptom but different root cause I'd like to share. I removed the localization as McCygnus hinted at (thanks for that) but still got the same exception on iPads, only. It turned out that my Info.plist file contained a link to an iPad specific main window nib file (MainWindow-iPad.nib). After removing that, everything worked.
I was able to solve this problem by simply restarting xcode. =/
精彩评论