Calling to function from UIBarButtonItem - iphone

I have button in my view with a setAction to a local function.
in GameOptions.m i have the next function:
- (void) changeSettings (UIBarButtonItem *) sender {
// do something
}
and a button that start it in GameOptions.m :
[btn1 addTarget:self action:#selector(changeSettings:) forControlEvents:UIControlEventTouchUpInside];
now i moved it from his view to a navigation controller as an rightBrButtonItem.
the myVC is an instance of small UIViewController with all the navigationBar settings,and each time i using pop ,push to it .
UIBarButtonItem *buttonNav1 = [[UIBarButtonItem alloc] initWithCustomView:settingsView];
[myVC.navigationItem setRightBarButtonItem:buttonNav1];
the problem is that this button is not in his GameOptions class and i want it to start the same function with implementation in GameOptions.m.
I would like to do the next thing :
buttonNav1 setAction:changeSettings;
but its impossible, the changeSetting is not recognized...
Tried : buttonNav1.action = self. but i'm not getting this function, only functions without parameters.
How can i call to chnageSettings from that button in navigationBar

All you need to do is inform your UIBarButtonItem of the existence of the GameOptions object.
That's what you were doing using self in :
[btn1 addTarget:self action:#selector(changeSettings:) forControlEvents:UIControlEventTouchUpInside];
Just after instanciating your UIBarButtonItem *buttonNav1, you can send it the message addTarget:action:forControlEvents: or, if you want to use setAction, don't forget to also use setTarget.
So now, your question is: what is the most elegant/efficient way to pass the GameOptions object's pointer to the UIBarButtonItem ;)

Related

How to pass multiple Selectors in UIButton

This is my code for a back button.
I have 9 buttons (button1,button2...button9)
And i want this button to activate if i press any of the other 9 buttons.
So is there a way where i can do this?
[_backButtonOutlet addTarget:self action:#selector(button1:) forControlEvents:UIControlEventTouchUpInside];
Create some method with will call all the desired methods that you want to call at the same time and call that method on button tapped event. Good Luck!
-(IBAction) button1:(id)sender
{
[self btn1Pressed:sender];
[self btn2Pressed:sender];
[self btn3Pressed:sender];
[self btn4Pressed:sender];
[self btn5Pressed:sender];
[self btn6Pressed:sender];
[self btn7Pressed:sender];
[self btn8Pressed:sender];
}
_backButtonOutlet is a reference to the button so you don't want it to be called when any buttons are pressed. button1: is the method that you want to be called when any button is pressed.
Option 1:
call:
[otherButtonOutlet_N addTarget:self action:#selector(button1:) forControlEvents:UIControlEventTouchUpInside];
on each of the other buttons (replace otherButtonOutlet_N as appropriate).
Option 2:
In your XIB / storyboard, connect all of the buttons to the button1: method. You can add multiple target/action pairs to a button.

UIBarButtonItem created using initWithCustomView doesn't trigger action

I'm updating some old code, and to make more room in a toolbar, I'm converting the Buttons from test to images. An example of the new and old code in loadView is this:
// New code, doesn't work.
UIButton *toggleKeyboardBtn = [UIButton buttonWithType:UIButtonTypeCustom];
toggleKeyboardBtn.bounds = CGRectMake( 0, 0, showKeyboardImage.size.width, showKeyboardImage.size.height );
[toggleKeyboardBtn setImage:showKeyboardImage forState:UIControlStateNormal];
UIBarButtonItem *toggleKeyboardItem = [[UIBarButtonItem alloc] initWithCustomView:toggleKeyboardBtn];
[toggleKeyboardItem setTarget:self];
[toggleKeyboardItem setAction:#selector(toggleKeyboard:)];
// Original code, works jut fine.
UIBarButtonItem *setupItem = [[[UIBarButtonItem alloc] initWithTitle:#"Setup" style:UIBarButtonItemStyleBordered target:[UIApplication sharedApplication].delegate action:#selector(showSetupView:)] autorelease];
My new code is copied from Cannot set action on UIBarButtonItem, and I'm fairly certain that I'm not making their mistake since my text button is working just fine.
showSetupView() is in my AppController.m file, and the setup screen appears and disappears as the button is pressed.
toggleKeyboard(), OTOH, is in the same file as the loadView() routine, and currently consists of this code:
//- (void)toggleKeyboard {
- (IBAction)toggleKeyboard:(id)sender {
NSLog(#"Entering toggleKeyboard()...");
hiddenKeyboard = !hiddenKeyboard;
[self prepareToolbarsAndStatusbar];
}
Needless to say, although I see the button-press animation, I never see the NSLog message. And one last observation, made by accident. Changing the setAction selector to this:
[toggleKeyboardItem setAction:#selector(noSuchRoutine:)];
compiles cleanly, possibly indicating that my routine name is being ignored for some reason.
Anyone have any ideas? Thanks.
I found the answer! In button action not responding iphone, it's said that the action and target need to be set on the UIButton, not the UIBarButtonItem. I don't know if that's new with the latest version of Xcode, but I guess it is since other questions (such as the one I mention above) use a different technique. Here's my new code:
UIButton *toggleKeyboardButton = [UIButton buttonWithType:UIButtonTypeCustom];
toggleKeyboardButton.bounds = CGRectMake( 0, 0, keyboardAddImage.size.width, keyboardAddImage.size.height );
[toggleKeyboardButton setImage:keyboardAddImage forState:UIControlStateNormal];
[toggleKeyboardButton addTarget:self action:#selector(toggleKeyboard) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *toggleKeyboardItem = [[UIBarButtonItem alloc] initWithCustomView:toggleKeyboardButton];
//[toggleKeyboardItem setTarget:self];
//[toggleKeyboardItem setAction:#selector(toggleKeyboard:)];
Though its too late, but for future references, I would like to quote apple docs for the method,
- (instancetype)initWithCustomView:(UIView *)customView;
The bar button item created by this method does not call
the action method of its target in response to user interactions.
Instead, the bar button item expects the specified custom view to
handle any user interactions and provide an appropriate response.
Did you try
-(void)toggleKeyboard
and
[toggleKeyboardItem setAction:#selector(toggleKeyboard)]; without :
and it made any difference? Is the method declared in the interface file?

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?

iPhone/iPad - issues with NavigationBar button?

I my application i have added button in NavigationBar like this..
UIBarButtonItem *more=[[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"search-25by25.png"] style:UIBarButtonItemStylePlain target:self action:#selector(SelectMission:)];
self.navigationItem.rightBarButtonItem = more;
When i am clicking on button application get's shutdown...
If i am doing same thing with normal button it's working fine can any one help me why it's behaving like this?
Try This
UIImage *i=[UIImage
imageNamed:#"search-25by25.png"];
UIButton *myButton = [UIButton buttonWithType:UIButtonTypeCustom];
myButton.bounds = CGRectMake( 0, 0, i.size.width, i.size.height );
[myButton setImage:i forState:UIControlStateNormal];
[myButton addTarget:self action:#selector(SelectMission:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *more=[[UIBarButtonItem alloc] initWithCustomView:myButton];
self.navigationItem.rightBarButtonItem
= more;
hope it helps :)
Have you looked in the code for SelectMission:? The code you've posted is only for presenting the button, which from your description appears to be working.
Also if there's anything being dumped into the console (Command-Shift-R)?
Judging by the crash log in your comment, I would say this has nothing to do with the UIBarButtonItem class in particular, and everything to do with your action handler. The crash logs tell the whole story: Your class does not implement a method called SelectMission: that takes one argument. Some caveats about the #selector keyword that you will want to double check:
1) Capitalization. Make sure that the method you implement is SelectMission:. Not selectMission:, selectmission:, Selectmission:, etc.
2) Arguments. The colon indicates that the method SelectMission: takes one argument. If you have implemented it and forgotten the argument it will crash with the exception you posted.
That should help narrow down the issue.

how to change uibutton title at runtime in objective c?

I know this question is asked many a times,and i am also implementing the same funda for chanding the title of the uibutton i guess.
Let me clarify my problem first. I have one uibutton named btnType, on clicking of what one picker pops up and after selecting one value,i am hitting done button to hide the picker and at the same time i am changing the the title of the uibutton with code
[btnType setTitle:btnTitle forState:UIControlEventTouchUpInside];
[btnType setTitleColor:[UIColor redColor] forState:UIControlEventAllEvents];
But with my surpriaze,it is not changed and application crashes with signal EXC_BAD_ACCESS. I am not getting where i am making mistake.I have allocated memory to the btnType at viewdidLoad. Also I am using
-(IBAction)pressAddType
{
toolBar.hidden = FALSE;
dateTypePicker.hidden = FALSE;
}
event on pressing the button to open the picker. Also i would like to mention that i have made connection with IB with event TouchUpInside for pressAddType.
Any guesses? I will be grateful if you could help me.
Thanks.
UPDATE:
#interface AddSettingPage : UIViewController<UITextFieldDelegate>
{
IBOutlet UIButton *btnType;
NSString *btnTitle;
}
#property (nonatomic, retain) IBOutlet UIButton *btnType;
-(IBAction)pressAddType;//:(id)sender;
Also
#synthesize btnType,btnTitle;
try
[yourButton setTitle:#"your title" forState:UIControlStateNormal];
[yourButton setTitle:#"your title" forState:UIControlStateSelected];
[yourButton setTitle:#"your title" forState:UIControlStateHighlighted];
when the picker is dismissed, the button (which was the control that hold focus) will be in the selected state (or the highlighted .. check it out).
and stop using UIControlEventTouchUpInside in the forState: parameter. it is not a state, it is an event. you are passing an event identifier instead of a state identifier
The state you pass in setTitle should be something like UIControlStateNormal:
[b setTitle:#"" forState:UIControlStateNormal];
Instead of
- (IBAction) pressAddType;
declare
- (IBAction) pressAddType:(id)sender; //or (UIButton *)sender
and define it like:
-(IBAction)pressAddType:(id)sender
{
toolBar.hidden = FALSE;
dateTypePicker.hidden = FALSE;
[(UIButton *)sender setTitle:btnTitle forState:UIControlEventTouchUpInside];
[(UIButton *)sender setTitleColor:[UIColor redColor] forState:UIControlEventAllEvents];
}
As you can see, you don't need to have your button as an ivar because it is passed as a parameter of the method when pressed.
This answer why not button title change only,EXC_BAD_ACCESS error only you getting when an object you trying to access those object is not in memory of stack or that object has null value. So my advice is please check your object (btnTitle) is in memory or not?