Objective C how to refer to a view in a class method - ios

My app has multiple views to add buttons programmatically and instead of having the following instance method in each controller, I would like to put the method in a common class as use it as a class method.
+ (void) addLeftImageButton:(UIButton *)leftButton:(float)x:(float)y:(NSString *)name:(int) tag
{
leftButton = [UIButton buttonWithType:UIButtonTypeCustom];
[leftButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[leftButton setTag: tag];
[leftButton setBackgroundImage:[UIImage imageNamed:name] forState:UIControlStateNormal];
leftButton.frame = CGRectMake(x, y, 345.0, 345.0);
[self.view addSubview:leftButton];
}
The question I have is how to refer self.view to the calling view. as self.view is not known in the common class.

You can't, a class method has no concept of self. You need to pass the view as a parameter.
+ (void)addLeftImageButton:(UIButton *)leftButton:(float)x:(float)y:(NSString *)name:(int) tag forView:(UIView *)view;

My personal recommendation is to leave the step of adding the subview to the controller itself, making this the class method:
+ (UIButton *) leftButtonWithImageName:(NSString *)imageName x:(CGFloat)x y:(CGFloat)y tag:(int)tag
{
UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeCustom];
[leftButton setTag: tag];
[leftButton setBackgroundImage:[UIImage imageNamed:name] forState:UIControlStateNormal];
leftButton.frame = CGRectMake(x, y, 345.0, 345.0);
return leftButton;
}
In a view controller:
UIButton *leftButton = [MyClass leftButtonWithImageName:#"image.png" x:0 y:0 tag:10];
[leftButton addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:leftButton];
A few reasons behind this:
If you're using this for multiple view controllers, your class method doesn't have to assume that they all implement the same buttonPressed: method, which isn't a safe assumption.
To someone just looking at your view controller code, it will look like nothing calls the buttonPressed:.
Callers of the leftButton... method will have more control over the button. For example, they might want to add the button as a property in viewDidLoad so its properties (like its frame) can be queried, but not actually add it to the screen until after an animation completes.
You might also consider making all the view controllers a subclass of a superclass, but that's a very implementation specific decision.

If this is a common method for all your controllers you should add it as an instance method in a base controller that all your other controllers inherit from.
Also, there are a few of weird things about that method:
Why do you pass leftButton as a parameter when the first thing you do is overwriting its value?
Your method declaration is really weird. Did you read the warnings? I think you want it to look more like this:
- (void)leftButtonWithImageName:(NSString *)name
x:(CGFloat)x
y:(CGFloat)y
tag:(int)tag
{
UIButton *leftButton = [UIButton buttonWithType:UIButtonTypeCustom];
[leftButton addTarget:self
action:#selector(buttonPressed:)
forControlEvents:UIControlEventTouchUpInside];
[leftButton setTag:tag];
[leftButton setBackgroundImage:[UIImage imageNamed:name]
forState:UIControlStateNormal];
leftButton.frame = CGRectMake(x, y, 345.0, 345.0);
[self.view addSubview:leftButton];
}

There are several ways to implement this . But a common class is not good one.
The best way is that you put this function as a category of UIViewController. This is instant method (-)but not class method(+)
You don't need to change others.
#import <UIKit/UIKit.h>
#interface UIViewControl (labels)
-(void) add left...
#end
#implementation UIViewControl (labels)
-(void) add left...{}
#end
Put above code in a file "labelcontrol.h" and "label control.m"
Then in your any viewcontroller.m
Add: import "labelcontrol.h" to make it work

Related

iOS Button action doesn't work

I have a strange issue with iOS UIButton.
I have a UIViewController class:
#interface CustomViewController : UIViewController
Inside of this class I have a label called customLabel. In this label I have a button subview:
UIButton *addButton = [[UIButton alloc] init];
[customButton setImage:[UIImage imageNamed:#"image"] forState:UIControlStateNormal];
[customButton addTarget:self action:#selector(customButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[customLabel insertSubview:customButton atIndex:1];
And of course, action method:
- (void)customButtonClicked
{
NSLog(#"- (void)customButtonClicked");
}
I also have a subclass for this view controller:
#interface MyNewCustomViewController : CustomViewController
This view controller is loaded inside UIWindow:
[self.navigationController pushViewController: myNewCustomViewController animated:YES];
Everything seems to be fine, label with button are at the correct positions, except the fact, that button click doesn't call action method...
Maybe you know, where the problem could be?
As long as you don't have another view over top of your current button and user interaction is enabled on the view. This should work.
// First make sure userInteractionEnabled is enabled for your custom label which will contain your button as a subview
customLabel.userInteractionEnabled = YES;
// Then create and add your button as a subview
UIButton *addButton = [[UIButton alloc] init];
[customButton setImage:[UIImage imageNamed:#"image"] forState:UIControlStateNormal];
[customButton addTarget:self action:#selector(customButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[customLabel addSubview:addButton]; // Places view on top index

Passing selector to a custom method to create UIButton programmatically

I am using XCode 5 under ios 7 to do a simple project. And I get the following error when I press a button that is created programmatically:
2013-11-10 09:16:02.969 Project2[446:70b] +[KNSunDynamicUIButton buttonSavePressed:]: unrecognized selector sent to class 0x221424
Details:
I create a custom method that is used to create a UIButton object programmatically. That custom method is used in any view controller. That custom method needs passed-in parameters like x, y, width, height, button title, and selector that is an event handler and passed in like "(SEL)selector".
Custom method (belongs to a helper class):
+(UIButton*)kNSunSetupWithSelector:(SEL)selector withX:(int)x y:(int)y width:(int)width height:(int)height
buttonTitle:(NSString*)buttonTitle backGroundColor:(CGColorRef) backGroundColor
{
UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"Save" forState:UIControlStateNormal];
button.frame = CGRectMake(x, y, width, height);
button.backgroundColor = [UIColor greenColor];
// selector is used over here
[button addTarget:self
action:selector
forControlEvents:UIControlEventTouchDown];
return button;
}
And then in a view controller .m file, I call that custom method like:
-(void)setUpButtons
{
SEL selector = #selector(buttonSavePressed:);
_buttonSave = [KNSunDynamicUIButton kNSunSetupWithSelector:selector withX:470 y:410 width:160 height:40 buttonTitle:#"Save" backGroundColor:(_buttonSaveColor)];
[self.view addSubview:_buttonSave];
}
#interface MyViewController ()
{
...
// buttons
UIButton* _buttonSave;
}
#end
And the definition of button's event handler in the same view controller .m file like:
- (void)buttonSavePressed:(UIButton*)button
{
NSLog(#"Button Save clicked.");
}
When I run my code and hit over the button, I see the exception as mentioned above. Please help thank you.
P.S. If I rewrite the custom method as an alternative that does not have "(SEL)selector" parameter in its signature, and let controller view, who calls that custom method, does the job of coding selector, then there is no exception:
-(void)setUpButtons
{
//Note: the codes are in my view controller .m file
_buttonSave = [KNSunDynamicUIButton kNSunSetupWithX:470 y:410 width:160 height:40 buttonTitle:#"Save" backGroundColor:_buttonSaveColor];
// Note: selector coding is taken care by codes of my view controller instead of by custom method
[_buttonSave addTarget:self
action:#selector(buttonSavePressed:)
forControlEvents:UIControlEventTouchDown];
[self.view addSubview:_buttonSave];
[_buttonSave setupView];
}
And the alternative custom method (I do not like the method because it does not take care of dynamic passed-in selector):
+(UIButton*)kNSunSetupWithX:(int)x y:(int)y width:(int)width height:(int)height
buttonTitle:(NSString*)buttonTitle backGroundColor:(CGColorRef) backGroundColor
{
UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"Save" forState:UIControlStateNormal];
button.frame = CGRectMake(x, y, width, height);
button.backgroundColor = [UIColor greenColor];
return button;
}
The problem is line in helper class:
[button addTarget:self action:selector forControlEvents:UIControlEventTouchDown];
Here you said that the helper class will have method you're passing through selector, in you're case buttonSavePressed: method.
You should add inController parameter in you're helper method to tell in which controller is selector method placed.
In your particular case, the helper method should looks something like this (Note that inController parameter is added right after selector parameter):
+(UIButton*)kNSunSetupWithSelector:(SEL)selector
inController:(UIViewController*)controller
withX:(int)x
y:(int)y
width:(int)width
height:(int)height
buttonTitle:(NSString*)buttonTitle
backGroundColor:(CGColorRef) backGroundColor
{
UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:#"Save" forState:UIControlStateNormal];
button.frame = CGRectMake(x, y, width, height);
button.backgroundColor = [UIColor greenColor];
// selector is used over here
[button addTarget:controller
action:selector
forControlEvents:UIControlEventTouchDown];
return button;
}
and you should call it, from your controller this way:
-(void) setupButtons
{
SEL selector = #selector(buttonSavePressed:);
_buttonSaveColor = [UIColor orangeColor].CGColor;
_buttonSave = [KNSunDynamicUIButton kNSunSetupWithSelector:selector
inController:self
withX:470
y:410
width:160
height:40
buttonTitle:#"Save"
backGroundColor:(_buttonSaveColor)];
[self.view addSubview:_buttonSave];
}

iPhone , Convert #Selector call whith IBAction

I have this code:
UIButton *btn1 = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *imgIcon = imageNamed(#"icon_1.png");
[btn1 setImage:imgIcon forState:UIControlStateNormal];
CGPointMake(textField.frame.size.width+textField.frame.origin.x+btnTalk.frame.size.width/2, textField.frame.origin.y+textField.frame.size.height/2);
[btnTalk addTarget:textField action:#selector(Hello:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btnTalk];
i can tap in UIbutton and it works
but i want to call with other button
i want create one IBAction for call this UIButton
i writes this code but doesn't work & textfield is (objectOfAnotherClass)
-(IBAction)call1
{
[textField Hello];
}
I think you should do like this:
[btnTalk addTarget:self action:#selector(Hello:) forControlEvents:UIControlEventTouchUpInside];
-(IBAction)call1
{
[self Hello:nil];
}
I think that you are looking for sendActionsForControlEvents that helps you to 'simulate' the action of touching the button... Here the method description.

How to create re-usable code in iOS for a custom back button

I have created a custom back button (code below). I've so far been re-pasting this block of code all through my app on every single page. I was wondering if someone could take my code as an example and give me pointers on how to throw this into one centralized location so that I wouldn't have to copy and paste it anymore.
I'm guessing this would go into a custom class .h and .m that I'd create but I'm not exactly sure what to do next as far as what the code itself would look like within the custom files.
// Create custom back button
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *backButtonImage = [UIImage imageNamed:#"back.png"];
[backButton setBackgroundImage:backButtonImage
forState:UIControlStateNormal];
[backButton addTarget:self
action:#selector(backButton)
forControlEvents:UIControlEventTouchUpInside];
[backButton setFrame:CGRectMake(0, 0, 40, 40)];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
[[self navigationItem] setLeftBarButtonItem:backButtonItem];
I would probably go with a category on UIViewController, with an interface like this:
#interface UIViewController (MyBackButton)
- (void)installBackButtonWithAction:(SEL)action;
#end
The implementation is the code from your question, with #selector(backButton) replaced by action:
#import "UIViewController+MyBackButton.h"
#implementation UIViewController (MyBackButton)
- (void)installBackButtonWithAction:(SEL)action {
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *backButtonImage = [UIImage imageNamed:#"back.png"];
[backButton setBackgroundImage:backButtonImage
forState:UIControlStateNormal];
[backButton addTarget:self
action:action
forControlEvents:UIControlEventTouchUpInside];
[backButton setFrame:CGRectMake(0, 0, 40, 40)];
UIBarButtonItem *backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
[[self navigationItem] setLeftBarButtonItem:backButtonItem];
}
#end
You might call it like this, for example:
- (void)viewDidLoad {
[super viewDidLoad];
[self installBackButtonWithAction:#selector(backButton)];
}
You could create a subclass of UINavigationController and have it be alter the navigationItem of any view controller that's pushed Ito its stack to set the custom back button. Then you just create an instance of your custom class instead of your current use of UINavigationController and every view controller will automatically get updated.
You could put that code into a category somewhere; given you're setting self as the target, `UIViewController might work. But, thats kind of ugly and relies on an assumption that your dismissal action will never change.
Something cleaner that you could do is refactor it a bit so that you create the button by passing in the target (self) and dismissal action (backButton) and have the category on UIBarButton instead.

Make UIButton act as navigationcontroller

How can I make a regular UIButton act as a navigationcontroller so that when it's pressed I can open up a new view?
Create yourButton in viewDidLoad method as following way...
UIButton *yourButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[yourButton setTitle:#"YearButton" forState:UIControlStateNormal];
yourButton.frame = CGRectMake(240, 40, 75, 30);
[yourButton addTarget:self action:#selector(buttonSelected:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:yourButton];
This is your method code and createViewController which is object of CreateViewController class and it is declared in .h file.....
-(void) buttonSelected:(id)sender{
if (!createViewController) {
createViewController = [[CreateViewController alloc] initWithNibName:#"CreateViewController" bundle:nil];
}
[self.navigationController pushViewController:createViewController animated:YES];
}
I think it will be helpful to you.
Assuming you are using a UINavigation controller in your project.
then for the buttons action just call
[yourUIButton addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchUpInside];
and for the method that gets called just do the following:
-(void)buttonAction{
[self.navigationController pushViewController:YourViewController animated:YES];
}

Resources