Есть в 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 производит компиляцию и сборку для всех таргетов проекта или рабочего пространства, не обращая внимания на то, какая схема и таргет в ней выбраны.
Добавить комментарий
Для отправки комментария вам необходимо авторизоваться.