Make all instances of UINavigationBar titles lowercase without subclassing? - ios

Some titles in this iOS app are defined in the storyboard. Some of the titles are being set programmatically. Is there a simple way (Obj-C categories maybe?) to make all the titles lowercase without subclassing?

It is possible with a bit of objective-c magic, using method_exchangeImplementations (AKA "Method Swizzling")
#import <objc/runtime.h>
#interface UINavigationItem (New)
#end
#implementation UINavigationItem (New)
- (void)setTitleLower:(NSString *)title {
[self setTitleLower:[title lowercaseString]];
}
+ (void)load {
method_exchangeImplementations(class_getInstanceMethod(self, #selector(setTitle:)), class_getInstanceMethod(self, #selector(setTitleLower:)));
}
#end
Now each call to someNavItem.title = #"Whatever" ([UINavigationItem setTitle:(NSString*)title]) should go through setTitleLower, which in turn also calls the original setTitle with a minor modification, lowercasing the title.
I would avoid having to implement such a category just for the sake of lower-casing all titles for each UINavigationItem. I guess you're experimenting categories.

Related

Change the value of textfield to another language when get textfield.text in iOS

when I get mytextfield.text the result is this: "۱۲۳۴" which is a Persian number of "1234".
I have a method which converts Persian text to English text.
I want to get the English text when getting text using mytextfield.text
solution 1:
I can realize when the user changes the textfield then I can change it to what I want. but its performance is not good because user might want to change it several time I just want to convert it when I want to get it.
How about creating a sub-class of UITextField and overriding .text?
In your .h file
#import <UIKit/UIKit.h>
#interface TranslatingTextField : UITextField
#end
In your .m file
#implementation TranslatingTextField
- (NSString *)text {
return MyTranslation(super.text); // Your translation is called here
}
#end
If you are using Interface Builder make sure to specify TranslatingTextField as the class for the text fields you want to use this class for.
Have you considered adding a UIButton with a IBAction, and only when the button is tapped, you get the text ?
#IBAction func buttonTapped(_sender : AnyObject){ // Here you get the text and convert it}
I probably do not understand your question, but I will try an answer anyway.
I assume your UITextField is setup in storyboard, and you defined an outlet from your code to it, something like
#property(nonatomic, weak) IBOutlet UITextField *mytextfield;
So you can access the textField by program by its identifier.
Or if you did setup the mytextfield by program anyway, you can also access it in the same way.
I assume, you know the times when you want to read mytextfield.text to convert the text to English, and I assume you have a method to convert the text to English, something like
-(NSString)convertToEnglish:(NSString *)text {…}
Why don’t you simply read the textField text and feed it into this method, like
NSString *englishText = [self convertToEnglish: mytextfield.text];
But as I said, I probably did not understand your question…
You can do this as you want using category in Objective-c, see the implementation below .
UITextField+Category.h
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
#interface UITextField (Category)
#end
NS_ASSUME_NONNULL_END
UITextField+Category.m
#import "UITextField+Category.h"
#implementation UITextField (Category)
- (NSString *)text {
return ConvertToEnglish(super.text); //Call your Util function From here
}
#end
Uses
#import "UITextField+Category.h"
- (void)whenYouWant {
//Just call txtName.text Call anywhere in the class :
NSLog(#"%#", self.txtName.text);
}

Access User-Defined Runtime Attributes in ViewController Programmatically iOS 7

Currently I have a BOOL in runtime attributes for my view controller that I use to see if my view controller should add a button to the navigation bar programmatically. I was told that to access the attribute in the code, you add a property with the same name like this:
#interface MyViewController
#property (nonatomic, assign) BOOL showButton;
#end
#implementation
#synthesize showButton = _showButton;
-(void)viewDidLoad {
[super viewDidLoad];
if (_showButton) {
//show button
}
}
#end
And this does work in iOS 8 and 9, but for some reason in the simulator, iOS 7 does not read the Boolean and it's always set to false.
I feel like this is a serious enough problem that someone should have an answer but Google or the search results on SO didn't seem to have results for this.
I really appreciate the help!
UPDATE: I set the value in the Storyboard.

Showing the same UIBarButtonItem on many views

I have a problem in my iOS application that I'm looking for some help with. I'm relatively new to iOS programming to I'm sure that there is some relatively simple solution to my problem.
First, I'm going to explain the hierarchy of the application:
It uses a UITabBarController to show a couple of different screens.
It uses a SWRevealViewController to show a sidebar
The sidebar is accessed from a Bar button item that is present in the Navigation bar of the application.
That the application uses SWRevealViewController https://github.com/John-Lluch/SWRevealViewController doesn't directly affect the problem that I have. If you are not familiar with this code base, just think of a Simple Bar Button that is shown at all times.
Now to the problem:
The Bar button that I want to show is associated with a few lines of code. (A property declaration and some methods).
This code should be used on a major part of the different view controllers in the application.
Now in the normal case, I'd just subclass UIViewController and make it the superclass of all my views that should show this button. However, my application should also show other types of views, such as a UITableViewController, so subclassing doesn't solve the entire problem.
If Objective-C supported Multiple Inheritance, I would make a class containing this code and let my other classes extend any subclass of UIViewController and my ugly support class at the same time.
Notes:
For now, my app is based on Storyboards
The TabBarController points to a number of UINavigationControllers, and not to any views that doesn't have a Navigation Bar.
I have tried implementing this with Objective-c Category where I add a category to UIViewController that does setup of my UIViewController. But I got stuck on this solution when I needed to add a #Property for the button and linking it to the XIB/Storyboard. Got the idea from this post Add the same UIBarButtonItem to several UIViewControllers but it doesn't contain any details.
tl;dr: I want to show the very same UIBarButtonItem on many of my applications views. The UIBarButtonItem is associated with some code, that is also the same for all these views.
What would be a good way to achieve this?
If i understood you correctly.
You want to show button for all your UIViewControllers.
There are many ways to achieve this. Please try this one.
1. Create a subclass of UIView with its XIB. It contains your button. create Properties and IBAction.
2. Implement your action on this subclass.
3. On .m file write the below code
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
{
if (![self.subviews count])
{
NSBundle *mainBundle = [NSBundle mainBundle];
NSArray *loadedViews = [mainBundle loadNibNamed:#"MyView" owner:nil options:nil];
return [loadedViews firstObject];
}
return self;
}
where, MyView is the name of your view.
4. Drag and drop a UIViewand place it on every `UIViewController XIB (or storyboard in your case) and set its custom class to "MyView" (or the name of your newly created class).
5. Run your project.
For reference: May i help you?
I have now solved this problem and I will post it here for reference:
This solves the problem with adding a sidebar button to several views in the project, but the code should be usable for any UIBarButton. The solution is the create a Category for UIViewController that specifies a setup method. This setup method is called from the different Views.
Category .h file:
#import <UIKit/UIKit.h>
#interface UIViewController (SidebarCompliance)
- (void)setupSidebar;
#end
Category .m file:
#import "UIViewController+SidebarCompliance.h"
#import "SWRevealViewController.h"
#implementation UIViewController (SidebarCompliance)
- (void)setupSidebar {
SWRevealViewController *revealViewController = self.revealViewController;
if (revealViewController) {
UIBarButtonItem *sidebarButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"menu.png"] landscapeImagePhone:[UIImage imageNamed:#"menu.png"] style:UIBarButtonItemStylePlain target:self.revealViewController action:#selector(revealToggle:)];
self.navigationItem.rightBarButtonItem = sidebarButton;
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
}
#end
And then an example of one of my views:
View .h file:
#import <UIKit/UIKit.h>
#import "UIViewController+SidebarCompliance.h"
#interface NumeroUno : UIViewController
#end
View .m file:
#import "NumeroUno.h"
#implementation NumeroUno
- (void)viewDidLoad {
[super viewDidLoad];
[self setupSidebar];
}
#end

how to update a UILabel's Text from AppDelegate.m file in Xcode?

I'm new in Objective-C Programming. I want to get the text from a UILabel and at least NSLog that when the application enters the background. but all i got was a null value.(I don't know why!). I'm using story boards to create the view and UILabel and i have used CTRL+Drag to hook the label to my code and synthesized that in the implementation file. but I just get a null value in AppDelegate.m codes.
These are my codes:
ViewController.h:
#property (strong, nonatomic) IBOutlet UILabel *Mylabel;
ViewController.m:
#synthesize Mylabel;
AppDelegate.m:
#import "ViewController.h"
- (void)applicationDidEnterBackground:(UIApplication *)application
{
ViewController * viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
NSLog(#"%#",[[viewController Mylabel] text]);
}
ViewController * viewController = (ViewController *)self.window.rootViewController;
NSLog(#"This is my text: %#", viewController.Mylabel.text);
As you're new to Objective-C, I will point out that you should not ever every capitalize your property values (AKA Mylabel). Always use camel case for properties and methods. Methods use [ ] to call, properties you use . notation to access and set. You also don't need to synthesize Mylabel as this is done automatically for you. I recommend looking at the iOS by Apprentice book provided by raywenderlich.com to get up to speed.
You are creating a new instance of ViewController in the applicationDidEnterBackground: method of AppDelegate.m, rather than accessing the existing instance. As a quick fix, you should find self.window.rootViewController points to your existing instance. So change your code to:
NSLog(#"Label text is %#",self.window.rootViewController.Mylabel.text);
Note the use of 'dot' notation to access properties (it's easier). And FYI, tradition has it that properties begin with a lowercase letter; you might want to change Mylabel to myLabel, to get into the habit!

Get current UIViewController from UIButton's class

I have custom UIButton which programmatically interacts (triggers) with ViewController methods via protocol. But the behaviour of the button has to be dependent on the ViewController placed on. I do this to minimise amount of code in ViewControllers itself, as the button has to remain the same and bear the same functions (navigation).
Is there any way in UIButton's custom class to get the ViewController it is placed on?
I'd follow #rmaddy advice in a specific way, borrowing from the SDK's style
// MyCutomButton.h
#protocol MyCustomButtonDatasource;
#interface MyCustomButton : UIButton
#property(weak,nonatomic) IBOutlet id<MyCustomButtonDatasource>datasource;
// etc
#end
#protocol MyCustomButtonDatasource <NSObject>
#optional
- (NSString *)howShouldIBehave:(MyCustomButton *)button;
#end
Now the button can have it's datasource set in IB. View controllers that include it will need a little additional code (sorry, it's unavoidable in a good design). They will declare themselves as implementing MyCustomButtonDatasource.
When MyCustomButton needs to behave conditionally based on where it's placed, it can ask its datasource...
// MyCustomButton.m
NSString *string = #"defaultBehavior"; // per #RichardTopchiy's suggestion
if ([self.datasource respondsToSelector:#selector(howShouldIBehave:)])
string = [self.datasource howShouldIBehave:self];
// string is just made-up here, have it answer something simple (int, BOOL)
// that lets the button proceed with the right behavior. Don't ask for
// anything that relies on specific knowledge of how MyCustomButton
// is implemented
EDIT - To create the relationship, if you've decorated the property as an IBOutlet (as shown above), you should be able to setup the relationship in IB. Declare your view controller as implementing <MyCustomButtonDatasource>. Select your custom button, then the connections inspector, then drag to your view controller.
Alternatively, make the button itself an IBOutlet property in the view controller and, in viewDidLoad, do:
self.customButton.datasource = self;
The last way to do it is give your button a tag, say, 128, then:
MyCustomButton *customButton = (MyCustomButton *)[self.view viewWithTag:128];
self.customButton.datasource = self;

Resources