problem with selector in iphone? - iphone

i am having a application where i am generating the uibuttons dynamically want to use same #selector...Now as sooon as event is generated i wanna check for values and pass it to thtroughthat selector how can i implement this code?
can anyone tell me a tutorial sort where buttons are dynamically generated and check for particular button click is depicted?
Plz help...

Not sure what do you call "dynamically"... Objective-c objects are always created dynamically. Perhaps you mean situation where you want to create series of very similar buttons with same code? Yes, it is quite a common task. For example in calculator like app, we need ten buttons with digits, why not create them with single block of code ? So:
- (void)makeButtons{
UIButton * aButton;
for(int i = 0; i < 10; i++){
aButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
aButton.frame = CGRectMake(0, i*45, 60, 40);
[aButton addTarget:self action:#selector(digitClick:) forControlEvents:UIControlEventTouchUpInside];
[aButton setTitle:[NSString stringWithFormat:#"%d",i] forState:UIControlStateNormal];
aButton.tag = i;
[self.view addSubview:aButton];
}
}
- (void)digitClick:(id)sender{
UIButton * aButton =(UIButton *)sender;
NSLog(#"cliced button with title %d",aButton.tag);
}
we use a tag property to find index of clicked button, it is often used way, but there are some other ways. For example store created buttons in array and then check if sender is equal to one of array elements:
...
if ([allButtons objectAtIndex:i] == sender)
...
If you want to pass some data, for example string from each button just create array with these objects and then access it using tag as index.

Try:
[self.button1 addTarget:self action:#selector(buttonTouchDown:) forControlEvents:UIControlEventTouchDown];
[self.button2 addTarget:self action:#selector(buttonTouchDown:) forControlEvents:UIControlEventTouchDown];
- (IBAction)buttonTouchDown:(id)sender
{
if (sender == self.button1) NSLog(#"Button-1");
if (sender == self.button2) NSLog(#"Button-2");
}

Related

How to hide buttons which I had allocated in for loop?

I have created 3 UIbuttons on the top of the screen. Now after clicking every button I got the 5 buttons for each at below with different background images. Below is the code for my first button(located at top) by which I got 5 images in my view controller.
-(IBAction) btnforimages1click:(id)sender {
for (int a=0; a<5 ; a++) {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
buttonsforbundle1 = [[UIButton alloc]initWithFrame:CGRectMake(100*a,300 ,100 ,90 )];
[buttonsforbundle1 addTarget:self action:#selector(btn4images1:) forControlEvents:UIControlEventTouchUpInside];
buttonsforbundle1.tag = a;
[buttonsforbundle1 setBackgroundImage:[UIImage imageNamed:[bundle1 objectAtIndex:a]] forState:UIControlStateNormal];
[self.view addSubview:buttonsforbundle1];
}
}
I do the same for other two buttons also. Now here I want is, when I click any of my top 3 buttons
I just want to display the related buttons (created in for loop)
I want to hide the other buttons related to other Top most buttons.
Please suggest me how to solve this.
You have at least three options:
1) Access UI element by tag:
If you can manage to issue unique tag number in your btnforimages1click, btnforimages2click, btnforimages3click for your other 5 added UIButtons, then you can access them:
UIButton *button = (UIButton *)[self.view viewWithTag:99];
[button removeFromSuperview];
2) Keep reference of the created buttons:
// in view.h
NSMutableArray *my_created_buttons;
...
// in view init
[[my_created_buttons alloc] init];
...
-(IBAction) btnforimages1click:(id)sender {
for (UIButton *b in my_created_buttons {
[b removeFromSuperview];
}
if([my_created_buttons count]) {
[my_created_buttons removeAllObjects];
}
... let buttonsforbundle1 local variable since we store current 5 button set in array
UIButton *buttonsforbundle1;
... in your for loop add this after creating and adding to view
[my_created_buttons addObject:buttonsforbundle1];
}
You can further refactor these code eg. by making mutablearray management to other method.
3) Keep it in Interface Builder
I think it is the easiest option, create 5 UIButtons in Interface Builder and have 5 IBOutlet for them. Then in your btnforimages1click you can eg:
-(IBAction) btnforimages1click:(id)sender {
self.IBbutton1 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:0]] forState:UIControlStateNormal];
self.IBbutton2 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:1]] forState:UIControlStateNormal];
self.IBbutton3 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:2]] forState:UIControlStateNormal];
self.IBbutton4 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:3]] forState:UIControlStateNormal];
self.IBbutton5 setBackgroundImage[UIImage imageNamed:[bundle1 objectAtIndex:4]] forState:UIControlStateNormal];
}
So you don't hide them, just change the background image. Moreover you don't have to deal with different touchUpInside event, use only one method, and in that one click method, you can distinguish between the different clicked UIButton by checking their tag (plus you have to use a variable to check which of the 3 top UIButton was clicked).

UIButton action with multiple argument [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Objective C: Sending arguments to a method called by a UIButton
i have a problem with uibutton action. I want send argument when the button clicked. i saw some examples that work with tag prop. and the class is id sender. but i dont want to fixed it. the action goes to my own manager. how can i do ?
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self
action:#selector(goToSubViewManager:)
forControlEvents:UIControlEventTouchUpInside];
here is the gotosubviewmng
- (void)goToSubViewManager:(ViewType*)vTipi
{
}
you should only use - (void)goToSubViewManager:(id)sender. or - (void)goToSubViewManager
so here are 2 ways to solve your problem.
you can use variables or property.
- (void)yourMethod
{
//your code
_vTipi = yourVTipi;
}
- (void)goToSubViewManager
{
//here you can use _vTipi;
}
you can add a Category for the UIButton , to add an id type property(such as #property(nonatomic) vTipi).faking instance variables for UIButton.(how to do you can look at this : http://oleb.net/blog/2011/05/faking-ivars-in-objc-categories-with-associative-references/) Then you can use like this:
- (void)goToSubViewManager:(id)sender
{
//you can user ((UIButton *)sender).vTipi
}
Use can use tag property of the button. And then can use that object by comparing the tag assigned.
UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[rightButton addTarget:self
action:#selector(goToSubViewManager:)
forControlEvents:UIControlEventTouchUpInside];
rightButton.tag=1;
//
then in the call back you can compare it as
- (void)goToSubViewManager:(id)sender
{
if(sender.tag==1){
// you can use an array of that object(if multiple), then apply your logic
}
}

How does this code work to create buttons?

I am wondering how exactly the following piece of code works (yes, it indeed works as intended, and it gives different values of tag, depending on which button was clicked.)
The point is: Aren't we reusing button 7 times, where are the other 6 buttons left? After executing this code do we really have memory reserved for 7 UIButtons?
Or as a more general question: Is this good programming style? The point is that I need to have a different action depending on which button was clicked, and this approach (with my limited objc skills) looked like the most straightforward.
Thanks in advance,
A beginning iOS developer.
UIButton *button;
for(int k=0;k<7;k++)
{
button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:#selector(aMethod:)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"" forState:UIControlStateNormal];
button.frame = CGRectMake(80, 20+30*k, 30, 30);
button.backgroundColor=[UIColor clearColor];
button.tag=k;
[subview addSubview:button];
}
Where the function aMethod: is defined as:
-(IBAction)aMethod:(id)sender
{
UIButton *clickedButton=(UIButton *) sender;
NSLog(#"Tag is: %d",clickedButton.tag);
}
No, you are not reusing the UIButton seven times: each iteration of the loop creates a new instance of UIButton in a call to the class method buttonWithType:, and assigns it to the variable of the same name:
[UIButton buttonWithType:UIButtonTypeCustom];
Your code would be better off if you declared that variable inside the loop:
for(int k=0;k<7;k++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
// ...the rest of the loop
}
This is a very good programming style for situations when your buttons perform very similar actions. For example, calculator buttons differ only in the number that they insert. When the buttons perform actions that differ a lot (e.g. insertion vs. deletion) you are better off creating them separately, not in a loop, and servicing their clicks using separate methods.
In this code you just create 7 buttons with different positions and tags. It is much more better, then duplicate creation code for 7 times. The one thing, that I can offer you - to create some enum for button tags to prevent code like this:
switch([button tag])
{
case 1:
// do something
break;
case 2:
// do something else
break;
case 3:
// exit
break;
.....
default:
assert(NO && #"unhandled button tag");
}
the code with enum values much more easy to read
switch([button tag])
{
case kButtonForDoSomething:
// do something
break;
case kButtonForDoSomethingElse:
// do something else
break;
case kButtonExit:
// exit
break;
.....
default:
assert(NO && #"unhandled button tag");
}
This code does suffice, you're creating 7 different buttons and adding them as subviews. Once you -addSubview:, the object is added to an array, Accessed via the .subviews property of UIView.
Although you should add UIButton *button in your for loop. So your code should look like below..
for(int k=0;k<7;k++)
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
....
}
If you needed to do something out of the for loop with the button then declaring it outside the loop makes sense, but this is not your case. Hope this helps.

IBAction used with Dynamically added UIbuttons

Good Evening all!
I have some UIButtons added dynamically into my view and of course I have an IBAction which handles button events.
The problem is: How can I detect which button is pressed if the only thing I know is the (id)sender and the array of buttons?
Buttons are never the same, every button has a different behavior. When I want to use static buttons and connect them through the IB I use something like this :
-(IBAction)doSomething:(id)sender
{
if(sender == button1)
dosomething;
if(sender == button2)
dosomething else;
if(sender == button3)
dosomething3;
}
In my case this does not work because there is no button1, button2, button3 but a MutableArray of buttons which have the same name as they were allocated with it. Button!
I tried using the way above but with no success and i tried also getting the tag of a button but I have nothing to compare it to!
I would really appreciate your help.
sincerely
L_Sonic
PS Dynamicaly means that i am creating the buttons in random time during run time like this
-(void)configActionSheetView
{
buttonView = [[UIView alloc]initWithFrame:CGRectMake(0.0,460, 60, 480)];
[buttonView setBackgroundColor:[UIColor blackColor]];
[buttonView setAlpha:0.6];
for (int i = 0 ;i<[buffButtons count];i++)
{
UIButton *customButton = [buffButtons objectAtIndex:i];
customButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//UILabel *customLabel = [[UILabel alloc]init];
//[customButton setTag:(i)+11];
[customButton addTarget:self action:#selector(activateBuffEffect:) forControlEvents:UIControlEventTouchUpInside];
[customButton setAlpha:1.0];
customButton.frame = CGRectMake(8.0, 5+(50*i), 44.0, 44.0);
[customButton setTitle:nil forState:UIControlStateNormal];
buttonView.frame = CGRectMake(0, 460, 60, 50+(44*(i+1)));
[buttonView addSubview:customButton];
}
}
this is inside a functions and gets called during run time. the buffButtons is a mutableArray with buttons that gets populated during runtime.
i need a solution like this i cannot get a different eventhandling method for everybutton.
When you was "added dynamically" I assume you mean that they are created from some piece of code. Since all buttons to different things and you know what a certain button should do, why don't you add different actions to different buttons?
UIButton *myCreatedButton = [[UIButton alloc] init];
[myCreatedButton addTarget:self
action:#selector(doSomething:)
forControlEvents:UIControlEventTouchUpInside];
UIButton *myOtherCreatedButton = [[UIButton alloc] init];
[myOtherCreatedButton addTarget:self
action:#selector(doSomethingElse:)
forControlEvents:UIControlEventTouchUpInside];
In the above code the target (set to self) is the class where the method you want to run is found, the action is the method that you want to run and the controlEvent is what should cause the method to run.
If you did it like this you would split the code in different methods like these (you do not need to specify them in the header):
-(void)doSomething:(id)sender {
// do somthing here ...
}
-(void)doSomethingElse:(id)sender {
// do somthing else here ...
}
This way you don't need to know what button was pressed since the correct code would get called anyway. Besides it makes it cleaner if you need to change the code for some of the buttons.
Found it!
-(IBAction)buttonTapped:(id)sender {
UIButton *btn = (UIButton *)sender;
NSLog(#"tapped: %#", btn.titleLabel.text);
[self anotherIBAction:sender];
}
now i can get the tag from the btn :D
thnk you!
Why not add a tag the button and then get the tag number from (id)sender in the selector function?

cocoa UIImageView addTarget with extra parameter

With a loop I add UIImageView to a UIScrollView i need to add an extra parameter addTarget so when i click i can log the index.
[imageButton addTarget:self action:#selector(buttonPushed:)
forControlEvents:UIControlEventTouchUpInside];
-(IBaction) buttonPushed: (int) index
{
NSLog(#"%d",index);
}
How do i achieve this?
When you add a target, the method being call can either have no arguments (e.g. buttonPushed) or have one (buttonPushed:) which is the control sending the event (in this case your button). If you want an index, or any other value, you need to set it on the button sending the event. For example, when you setup the buttons:
myButtons = [NSArray arrayWithObjects:myFirstButton, mySecondButton, nil];
[myFirstButton addTarget:self action:#selector(buttonPushed:)
forControlEvents:UIControlEventTouchUpInside];
[mySecondButton addTarget:self action:#selector(buttonPushed:)
forControlEvents:UIControlEventTouchUpInside];
and implement your action as
- (IBaction)buttonPushed:(UIButton *)button
{
NSLog(#"%d",[myButtons indexOfObject:button]);
}
Use the tag property of the button