Есть в Xcode отличная возможность сразу в интерфейсе Interface Builder видеть итоговый результат отрисовки отличных от стандартных компонентов. Например, вы можете сделать свою кнопку с обводкой, добавив три свойства:
IB_DESIGNABLE @interface MyButton : UIButton @property (nonatomic, assign) IBInspectable CGFloat lineWidth; @property (nonatomic, assign) IBInspectable CGFloat cornerRadius; @property (nonatomic, copy) IBInspectable UIColor *lineColor; @end
Значения этим свойствам можно буден назначить в панели инспектора при редактировании xib или storyboard, а при правильной реализации класса эти изменения тут же отобразятся на вашей кнопке. Подробнее прочитать можно тут, тут и в официальной документации.
Я же хочу поделиться результатом компиляции нескольких идей относительно локализации объектов, находящихся в xib или storyboard.
В комментария к статье iOS Localization: XLIFF была предложена идея использовать IBInspectable свойство для задания ключа локализации, который в коде используется для доступа к строкам из файлов Localizable.strings:
@property (nonatomic, copy) IBInspectable NSString *locKey;
а в реализации метода-сеттера предполагалось просто установить строку:
-(void)setLocKey:(NSString *)locKey
{
_locKey = [locKey copy];
NSString *locString = NSLocalizedString(locKey, nil);
[self setTitle:locString forState:UIControlStateNormal];
}
Однако, предложенная идея базируется на наследовании. Можно улучшить её, воспользовавшись удобным механизмом категорий, который расширяет существующие классы, что несомненно даёт возможность строить более гибкие архитектуры с меньшим числом зависимостей:
@interface UIView (Localizables)
@property (nonatomic, copy) IBInspectable NSString *locKey;
@end
@implementation UIView (Localizables)
-(void)setLocKey:(NSString *)locKey
{
if (locKey && locKey.length > 0) {
NSString *locString = MLLocalizedString(locKey, nil);
// Button
if ([self isKindOfClass:[UIButton class]]) {
[((UIButton*)self) setTitle:locString forState:UIControlStateNormal];
}
// Label
else if ([self isKindOfClass:[UILabel class]]) {
[((UILabel*)self) setText:locString];
}
// Text View
else if ([self isKindOfClass:[UITextView class]]) {
[((UITextView*)self) setText:locString];
}
// Text Field
else if ([self isKindOfClass:[UITextField class]]) {
[((UITextField*)self) setText:locString];
}
// Image View
else if ([self isKindOfClass:[UIImageView class]]) {
[((UIImageView*)self) setImage:[UIImage imageNamed:locString
inBundle:[NSBundle bundleForClass:[AppDelegate class]]
compatibleWithTraitCollection:nil]];
}
}
}
-(NSString *)locKey
{
return nil;
}
@end
Стоит отметить, что если использовать стандартный макрос NSLocalizedString(), то в механизме отрисовки будет происходить небольшой сбой, описанный в данной статье, а конкретно — вместо строки из Localizable.strings будет отображаться ключ locKey, так как +mainBundle в макросе будет возвращать не бандл вашего приложения, а другой.
Чтобы исправить это недоразумение, сделаем свой макрос на основе оригинального и чуть-чуть его подредактируем:
// Localization for IB support #define MLLocalizedString(key, comment) \ [[NSBundle bundleForClass:[AppDelegate class]] localizedStringForKey:(key) value:@"" table:nil] #define MLLocalizedStringFromTable(key, tbl, comment) \ [[NSBundle bundleForClass:[AppDelegate class]] localizedStringForKey:(key) value:@"" table:(tbl)]
Здесь AppDelegate — это класс-наследник от UIResponder, который используется в нашем приложении, тем самым возвращаемый NSBundle гарантированно будет относиться к нашему приложению и будет содержать строки Localizable.strings.
К сожалению, описанный ниже приём сработал лишь один раз и более не воспроизводил описанный результат. В чем причина, я пока не разобрался.
Если вам требуется, чтобы Interface Builder выбирал для отображения конкретный язык, установите в настройках текущей выбранной схемы аргументы запуска:
- выбрать схему
- выбрать Edit Scheme в выпадающем меню
- выбрать Run
- выбрать Arguments
- добавить -AppleLocale de_De
- выбрать -AppleLanguages (de)
Если у вас несколько схем, то после переключения достаточно выбрать в меню Editor пункт Refresh All Views и после успешной пересборки в Interface Builder отображаемые строки заменятся на соответствующие выбранной схеме.
Единственный недостаток – это время, которое занимает пересборка: если ваш Mac не самый быстрый, придётся терпеливо выжидать, пока пройдёт компиляция и обработка ресурсов. Так же раздражает, что IB производит компиляцию и сборку для всех таргетов проекта или рабочего пространства, не обращая внимания на то, какая схема и таргет в ней выбраны.
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.