About issue related to IBInspectable in localisation - ios

In my app i set localisation text using IBInspectable string and also change language using manually using button action.
Issue
I can't able to refresh UI while change language manually. I need to refresh IBInspectable string while I change language.

I have achieved using below code :
1. InterFace and Implementation for UIView
#interface UIView (AdditionLocalization)
-(void)applyLocalization;
#end
#implementation UIView (AdditionLocalization)
-(void)applyLocalization{
if ([self isKindOfClass:[UILabel class]]) {
UILabel *lbl = (UILabel *)self;
[lbl setLocalizedText:lbl.accessibilityLabel];
}
}
2. InterFace and Implementation for Label
IB_DESIGNABLE
#interface UILabel(LabelAdditionLocalizations)
#property (nonatomic,copy)IBInspectable NSString *localizedText;
#end
#implementation UILabel(LabelAdditionLocalizations)
#dynamic localizedText;
-(void)setLocalizedText:(NSString *)localizedText{
self.text = [UtilityClass get:localizedText.length>0 ? localizedText : self.text alter:#""];
self.accessibilityLabel = localizedText.length>0 ? localizedText : nil;
}
3.Trigger Manually while button click
- (IBAction)clickChangeLanguage:(id)sender {
[UtilityClass setLanguage:current];
for (UIView *view in self.view.subviews) {
[view applyLocalization];
}
}

Related

AutoLayout without usage of Storyboards or Interface Builder

I am building an app where I want to completely avoid using Storyboard and Interface Builder in general, so all UI should be specified in code. I am using PureLayout, a nice API for configuring AutoLayout constraints.
However, my issue is that it seems like AutoLayout is disabled when not using Interface Builder. updateViewConstraints, the method where I put the layout according to the recommendation given by the PureLayout author, is not called at all.
Just to give a bit more info about my setup:
deleted Main.storyboard and removed the entry from my Info.plist
manually setup self.window in AppDelegate.m and added UINavigationController with MainMainController as rootViewController
As mentioned, my main issue is that updateViewConstraints does not get called on MainViewController but the UI elements are all displayed with the frames that I passed to them during initilization.
Note: It seems to me like I just need to enable some flag somewhere to mimic the checkbox from Interface Builder with which you can indicate whether you want to use AutoLayout.
MainViewController.m
#interface MainViewController ()
#property (nonatomic, strong) UIButton *startButton;
#property (nonatomic, assign) BOOL didSetupConstraints;
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.view addSubview:self.startButton];
[self.view setTranslatesAutoresizingMaskIntoConstraints:NO];
}
- (UIButton *)startButton
{
if (!_startButton) {
UIButton *startButton = [UIButton buttonWithType:UIButtonTypeSystem];
CGRect startButtonFrame = CGRectMake(75.0, 75.0, 250.0, 44.0);
startButton.frame = startButtonFrame;
[startButton setTitle:#"Start" forState:UIControlStateNormal];
[startButton setTranslatesAutoresizingMaskIntoConstraints:NO];
_startButton = startButton;
}
return _startButton;
}
- (void)updateViewConstraints
{
NSLog(#"Update view contraints");
if (!self.didSetupConstraints) {
[self.startButton autoCenterInSuperview];
self.didSetupConstraints = YES;
}
[super updateViewConstraints];
}
#end

Copy UITextField string to UITextView

How Can I copy UITextField string to UITextView?
I want to do it when UIButton;
[myUIButton addTarget:self action:#selector(touchButton) forControlEvents:UIControlEventTouchUpInside];
UITextField* textField (initialized, omit code here)
[self.view addSubview:textField];
//save string to the property
self.textFieldString = textField.text;
//textFieldString is #property NSString* textFieldString; at the header.
UITextView* textView (initialized, omit code here)
[self.textView setEditable:false];
[self.view addSubview:self.textView];
//here i want to implement UITextField string -> UITextView display
-(void)submitButtonClicked {
//....
//Problem i am having here is that, I can not see instance variable other than #property variable. How should I pass UITextField .text to UITextView?
}
Prepare the identifier to each UI
[textField setTag:100];
[self.view addSubview:textField];
[textView setTag:200];
[self.view addSubview:textView];
Identify the each UI element and Manage
-(void)submitButtonClicked {
//Problem i am having here is that,
// I can not see instance variable other than #property variable.
// How should I pass UITextField .text to UITextView?
UITextField *myTextField=(UITextField*)[self.view viewWithTag:100];
UITextView *myTextView=(UITextView*)[self.view viewWithTag:200];
myTextView.text=myTextField.text;
}
If you are creating UITextView programatically then create a property variable and synthesize the same. You can access the same using the synthesized name and in UIButton action method get the text and set it to UITextView.
In .m file you can declare UITextView as
#interface classname () {
UITextView *textView
}
or in .h file
#property (nonatomic, strong) UITextView *textView;
As you have described the problem 'Problem i am having here is that, I can not see instance variable other than #property variable. How should I pass UITextField .text to UITextView?'
In your button's action use:
textView.text=textField.text;
Declare your variables between #interface and #end and initialize them in the viewDidLoad. This way you'll be able to use them in your button's action.
#interface ViewController ()
{
UITextView *textView;
UITextField *textField;
}
#implementation ViewController
-(void) viewDidLoad
{
// Do the following
// Initialize both textView and textField
// Set their frames
// Add both of them as a subview to your view
}
#end
Now you'll be able to access both of them in your button's action.
Hope this helps.

iOS Storyboard localizable strings do not work on UILabel subclasses

I'm using the new iOS functionnality to translate the storyboards (http://developer.apple.com/library/ios/#referencelibrary/GettingStarted/RoadMapiOS/chapters/InternationalizeYourApp/InternationalizeYourApp/InternationalizeYourApp.html)
The problem with this solution, it does not work with my UILabel subclasses.
Here are the codes for my UILabel subclasses :
.h:
#import <UIKit/UIKit.h>
#interface LabelThinText : UILabel
- (void)awakeFromNib;
-(id)initWithFrame:(CGRect)frame;
#end
.m :
#implementation LabelThinText
- (void)awakeFromNib
{
[super awakeFromNib];
[self setFont:[UIFont fontWithName:#"Raleway-Light" size:[[self font] pointSize]]];
}
-(id)initWithFrame:(CGRect)frame
{
id result = [super initWithFrame:frame];
if (result) {
[self setFont:[UIFont fontWithName:#"Raleway-Light" size:[[self font] pointSize]]];
}
return result;
}
#end
I guess i'm missing something to get the automatic translations from my Storyboard.strings file.
Anyone has an idea ?
Thanks !
I ran into the same problem, and for the same reason, setting a custom font in a label. My strategy was a little more general, though. My custom font is Helvetica-like, so I used Helvetica Neue in IB as a placeholder font. The UILabel subclass translated that to my custom font, preserving font size and weight, so I could control all that through IB.
That made my workaround for the translation bug (I assume it's a bug) easier. I traverse all my views recursively in viewDidLoad, and map all UILabel fonts if they match the placeholder font, and the same for UIButton in my case.
Have you filed a bug?
Encountered the same problem, here's how I got around it:
Drop your custom class, and create a category on UILabel, in your case UILabel+ThinText:
- (void) setThinText:(BOOL)thinText
{
if (thinText) {
[self setFont:[UIFont fontWithName:#"Raleway-Light" size:[[self font] pointSize]]];
}
}
In your storyboard, select your label, choose the Identity Inspector and add the following User Defined Runtime Attribute:
Keypath: thinText – Type: Boolean – Value: checked
I got this issue too. I solve it setting the custom font in each ViewController. Let me show you an example:
CustomViewController.h
#interface CustonViewController
#property (strong, nonatomic) IBOutlet UILabel* someLabel;
#end
The in CustomViewController.m
- (void)viewDidLoad
{
[self setUoFonts];
}
- (void)setUpFonts
{
self.someLabel.font = [UIFont fontWithName:#"AmaticSC-Regular" size:self.someLabel.font.pointSize];
}
And that's it!. You're going to have your translation and your custom font.
Remember to remove the custom class from StoryBoard.

Possible to use a getter to configure UIButtons an d UIViews in iOS?

I regularly use lazy loading to instantiate custom classes, arrays, etc. The pattern is typically:
#property (strong, nonatomic) Class *class;
...
- (Class *)class
{
if(!_class) _class = [[Class alloc]init];
return _class;
}
Is it possible to use the same pattern to configure UI elements? For example, instead of formatting all my buttons and views in ViewWillAppear, I would like to put the formatting in the getter. For example:
- (UIButton *)button
{
if(!_button) {
_button = [[UIButton alloc]init];
self.button.backgroundColor = [UIColor redColor];
}
return _button;
}
The problem is I am using a storyboard and XCode instantiates the button so asking if it is nill should always return false. So the background will never be changed. If I remove the if-then, then the background will be set every time the getter is accessed which is probably OK but not optimal.
So, how do I use a UI element's getter to configure the element?
If this is really the way you want to do it, just use a BOOL flag. For example:
#interface MyClass() {
BOOL _hasCustomisedButton;
}
#property (strong, nonatomic) UIButton *button;
#end
#implementation MyClass
- (UIButton *)button {
if (_hasCustomisedButton || _button == nil) {
// check for nil button as well in case the nib isn't loaded yet
return _button;
}
[_button setBackgroundColor:[UIColor redColor]];
_hasCustomisedButton = YES;
return _button;
}
#end

Accessing UIButton from another class not working?

I am trying to access my UIButton in my Play class from my CCLayerClass.
The problem is that it is not working!
Here is how I declare it in the Play class:
.h
IBOutlet UIButton *pauseButton;
#property(nonatomic, retain) IBOutlet UIButton *pauseButton;
.m
#synthesize pauseButton;
Then in the dealloc:
[pauseButton release];
Also of course I connect it then in Interface builder.
Then in my other class (My CCLayer) class. I try to do this:
Play *play = [[[Play alloc] init] autorelease];
[play.pauseButton setHidden:YES];
The thing is, is that it simply just does not hide the button. Is there any reason for this?
Thanks!
Edit1:
My Play.h
IBOutlet UIButton *pauseButton;
BOOL pauseButtonVisible;
#property(nonatomic, retain) IBOutlet UIButton *pauseButton;
#property(readwrite) BOOL pauseButtonVisible;
.m
#synthesize pauseButton;
- (void)setPauseButtonVisible: (BOOL) variableToSet {
pauseButtonVisible = variableToSet;
if(pauseButton)
[pauseButton setHidden: !pauseButtonVisible];
}
- (BOOL) pauseButtonVisible
{
return(pauseButtonVisible);
}
viewWillAppear:
[pauseButton setHidden: !pauseButtonVisible];
I also made sure I connected it in Interface Builder
Then in CCLayerClass I do this:
Play *play = [[[Play alloc] init] autorelease];
if(play.pauseButton == NULL) {
NSLog( #"pause button is NULL");
}
But that NSLog gets called! Why is my pauseButton NULL? I just need to alloc it so it stays alive, is that possible?
Thanks!
play.pauseButtonVisible = YES;
Okay. Hopefully third time is the charm (and after that, I'm giving up cause it's time for me to go to bed).
Here in the .h file, I'm keeping the new pauseButtonVisible BOOL property.
#interface Play : UIViewController
{
BOOL pauseButtonVisible;
IBOutlet UIButton *pauseButton;
}
#property(nonatomic, retain) IBOutlet UIButton *pauseButton;
#property(readwrite) BOOL pauseButtonVisible;
#end
But in the .m file, we're doing something a little different:
#interface Play
// here we are rolling our own setters and getters
// instead of #synthesizing...
- (void)setPauseButtonVisible: (BOOL) variableToSet
{
pauseButtonVisible = variableToSet;
if(pauseButton)
[pauseButton setHidden: !pauseButtonVisible];
}
- (BOOL) pauseButtonVisible
{
return(pauseButtonVisible);
}
- (void) viewWillAppear: (BOOL) animated
{
[pauseButton setHidden: !pauseButtonVisible];
[super viewWillAppear: animated];
}
and
Play *play = [[[Play alloc] init] autorelease]; // you should really be using initWithNibName, but anyways
play.pauseButtonVisible = YES;
So now, hopefully pause button will be visible or hidden at the appropriate time for while your code is running.

Resources