Button #selector not working if button defined in NSObject - ios

I have the following problem: I am trying to define a button in an NSObject (in a separate file) and add it to my ViewController:
NSObject method:
in obj.h:
+(void)NewButtonInView:(UIView *)view withAction:(SEL)actionbutton;
in obj.m
+(void)NewButtonInView:(UIView *)view withAction:(SEL)actionbutton {
UIButton *button = [[UIButton alloc] init];
button.frame = CGRectMake(0, 0, 50, 50);
[button addTarget:self action:actionbutton forControlEvents:UIControlEventTouchUpInside];
}
in my ViewCotroller I import the obj.h and:
[obj NewButtonInView:[self view] withAction:#selector(actionB:)];
and:
-(void)actionB:(UIButton *)button {
//some code
}
The button looks fine but when I click it I get the following error:
"[obj actionB:]: unrecognized selector sent to class"
Any help is appreciated.
Thank you.

the problem is this line
[button addTarget:self action:actionbutton forControlEvents:UIControlEventTouchUpInside];
specifically, the use of self. You put the actionB: method in the viewController, but because the NewButtonInView:withAction: method is in a class method of obj self refers to the class obj. To fix it pass in the view controller as a parameter to the method like this
+(void)NewButtonInView:(UIView *)view withAction:(SEL)actionbutton target: (id) target {
UIButton *button = [[UIButton alloc] init];
button.frame = CGRectMake(0, 0, 50, 50);
[button addTarget: target action:actionbutton forControlEvents:UIControlEventTouchUpInside];
}

Try defining it with a return value, as follows:
+(UIButton *)NewButtonInView:(UIView *)view withAction:(SEL)actionbutton withTarget:(id)target{
UIButton *button = [[UIButton alloc] init];
button.frame = CGRectMake(0, 0, 50, 50);
[button addTarget:target action:actionbutton forControlEvents:UIControlEventTouchUpInside];
return button;
}
Then when you call it:
UIButton *button = [obj NewButtonInView:[self view] withAction:#selector(actionB:) withTarget:self];
Not sure why you're doing it in an NSObject instead of in your view controller, but that's the way to go about it if you do.

Related

How do I know which class this button is in for the action?

How do I know which class this button is in for the action?
When I touch the button then perform touchButton method, I want to know which class this button is in ?
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(200, 400, 100, 100);
button.backgroundColor = [UIColor orangeColor];
[self.view addSubview:button];
[button addTarget:self action:#selector(touchButton)
forControlEvents:UIControlEventTouchUpInside];
}
- (void)touchButton{
NSLog(#"How do I know which class this button is in for the action?");
}
you can use for the compare -
- (IBAction) touchButton:(id)sender {
UIButton *btn = (UIButton *) sender;
if([btn.class isMemberOfClass:<#(__unsafe_unretained Class)#>]){
/// write your code here....
}
}

Is there a way of doing an action locally on a UIButtton?

I am setting up a table with an I have this code:
UIButton *done = [[UIButton alloc]initWithFrame:CGRectMake(20, 25, 40, 40)];
[done setImage:[UIImage imageNamed:#"unchecked.png"] forState:UIControlStateNormal];
[done addTarget:self action:#selector(done:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:done];
return cell;
This doesn't work beacuse this button is only declared in this scope and I want to simply change its image on this click
Change the image in the done: method.
- (void)done:(id)sender
{
UIButton *button = (UIButton *)sender;
[button setImage:[UIImage imageNamed:#"yourImage.png"]
forState:UIControlStateNormal];
}
What does you done method look like?
I think that if you add a sender argument to the method, you can access the button.
- (void)done:(id)sender
{
UIButton *button = (UIButton*)sender;
[button doStuff];
}
You have to declare an ivar or a private/public property. So you can change its image from everywhere, for example:
#interface ViewController ()
#property UIButton *done;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.done = [[UIButton alloc]initWithFrame:CGRectMake(20, 25, 40, 40)];
[self.done setImage:[UIImage imageNamed:#"unchecked.png"] forState:UIControlStateNormal];
[self.done addTarget:self action:#selector(done:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.done];
}
- (void)done:(UIButton *)sender
{
//Do something.. like change image
[self.done setImage:[UIImage imageNamed:#"checked.png"] forState:UIControlStateNormal];
}
#end
Or you declare the sender as the UIButton, like this:
- (void)done:(id)sender
{
UIButton *done = (UIButton *)sender;
//Do something with the button
}

Setting selectors for global UIButton

I want to return a global UIButton from a global class.
+(UIBarButtonItem *) globalButton {
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame = CGRectMake(0.0, 0.0, 40, 40);
[myButton addTarget:self action:#selector(???)
forControlEvents:UIControlEventTouchUpInside];
return myButton;
}
So if I call [Global globalButton] from my viewController, I can get this button. The problem I'm having is how to set the selector, if I'm calling if from my view controller?
You should change your code as follow, assuming you would be calling it from UIViewController
+(UIButton *) globalButton:(UIViewController*)delegate {
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame = CGRectMake(0.0, 0.0, 40, 40);
if([delegate respondsToSelector:#selector(gloBalButtonTapped:)])
[myButton addTarget:delegate action:#selector(gloBalButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
return myButton;
}
//Below method should be present in your view controller than only it will be added to myButton click event.
-(IBAction)gloBalButtonTapped:(id)sender{
}
You should return UIButton only if you are creating UIButton, if you need to return UIBarButtonItem than you should create UIBarButtonItem or Xcode will give warning, just a suggestion though.
Just dont add target in Global Class wherever you want to use it just use it like this.
UIBarButtonItem *btn = [Global globalButton];
btn addTarget:self action:#selector(yourSelector)
forControlEvents:UIControlEventTouchUpInside];
Or you can make globalButton a property in GlobalClass and write this method in setGlobalButton and then you can use it as a property in any viewController.
Or if you want to control it in Global only then you can mention your selector mentioned in this class only. And in that method you can control the behaviour.
Try this in your controller:
UIBarButtonItem* button = [UIBarButtonItem globalButton];
[button addTarget:self action:#selector(yourDidTapAction:) forControlEvents:UIControlEventTouchUpInside];
or this in globalButton:
+(UIBarButtonItem*)globalButtonWithTarget:(id)target andAction:(SEL)action
{
// ...
[myButton addTarget:target action:action
forControlEvents:UIControlEventTouchUpInside];
// ...
}
I found the easiest way to do this is below:
+(UIBarButtonItem *) buttonWithSelector:(SEL)selector andSender:(id)sender {
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.frame = CGRectMake(-40.0, 10.0, 40, 40);
[myButton addTarget:sender action:selector forControlEvents:UIControlEventTouchUpInside];
return myButton;
}

Can't pass UIButton image with viewWithTag

I don't understand why I'm getting "[UIScrollView imageView]: unrecognized selector sent to instance"
for (int i=0;i<[imagesForGame count];i++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(i*310, 0, 310, 200);
[button setImageWithURL:[NSURL URLWithString:[imagesForGame objectAtIndex:i]] forState:UIControlStateNormal];
[button addTarget:self action:#selector(openFullPic:) forControlEvents:UIControlEventTouchUpInside];
[_myScroller addSubview:button];
}
-(void)openFullPic:(UIButton *)sender
{
UIButton *random = (UIButton *)[_myScroller viewWithTag:sender.tag];
UIImageView *test = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 300, 300)];
test.image = random.imageView.image; // <-- Error
...
}
The sender will be a button anyway, so use it instead.
-(void)openFullPic:(UIButton *)sender
{
UIButton *random = (UIButton *)sender;
UIImageView *test = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 300, 300)];
test.image = random.imageView.image; // <-- No more error.
...
}
Because you never set the tag for the button.
Do in the first loop, button.tag = i;
You have UIButtons instance in sender variable so you don't need to use viewWithTag at all ;-)

ACTION for UIBUTTON in iOS

I have one custom class with subclass of UIView, inside this I created one button dynamically.
Now I want to set Action for button method. I set normal like UIviewController.
But its not working.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UIButton *but=[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
but.frame= CGRectMake(200, 15, 15, 15);
[but setTitle:#"Ok" forState:UIControlStateNormal];
[but addTarget:self action:#selector(aMethod)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:but];
// Initialization code
}
return self;
}
-(void)aMethod
{
NextEyeViewController *nexteye=[[NextEyeViewController alloc]initWithNibName:#"NextEyeViewController" bundle:nil];
[self presentViewController:nexteye animated:YES completion:nil];
}
-(void)aMethod is my method name for button
If you want to set an action to your button created programmatically you need to do like this :
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button addTarget:self
action:#selector(aMethod)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Show View" forState:UIControlStateNormal];
button.frame = CGRectMake(0.0, 0.0, 160.0, 40.0);
[view addSubview:button];
Create UIButton:
UIButton *yourButton = [[UIButton alloc] initWithFrame:frameButton];
// Here code to set button properties: color, label...
[yourButton addTarget:self action:#selector(aMethod) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:yourButton];
Your method has to receive the sender of the action:
-(void)aMethod:(id)sender {
// your code
}
Update:
You also have to call your method suitably with #selector(aMethod:) instead of #selector(aMethod).

Resources