UINavigation Bar Button, change IBAction depending on click - iphone

Ok so at the moment i have a navigation controller with a right button which logs a user in.
however I want to change the login button to logout once it has been clicked and this logout button will call a different IBAction.
to help visualize this.
As default, I have a right button on the navigation controller which says login, once this login button is pressed the ibaction login:(id)sender is pressed.
what i want to do is change the button to logout and call logout:(id)sender when it is clicked.
is this possible.
thanks.

You can just change what the button does when it is pressed:
- (void)login:(UIButton*)button {
[button setTitle:#"Logout"];
[button setAction:#selector(logout:)];
}
- (void)logout:(UIButton*)button {
[button setTitle:#"Login"];
[button setAction:#selector(login:)];
}
Alternately, since the button is on the UINavigationBar, you could instead do this:
-(IBAction)login:(id)sender{
UIBarButtonItem *logoutButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(logout:)];
[[self navigationItem] setRightBarButtonItem:logoutButton];
[logoutButton release];
}
-(IBAction)logout:(id)sender{
UIBarButtonItem *loginButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
target:self
action:#selector(login:)];
[[self navigationItem] setRightBarButtonItem:loginButton];
[loginButton release];
}

You can set two different titles or image for the button, one for normal/default state and other for selected state.
Similarly, you can set two different operation based on the state of the button.
So, if button is in normal/default state, user needs to login. Once user does login, we put the button into selected state.
Thus, if button is in selected state, user needs to log out.
In this way, we can keep toggling the states of the same button, to do two different operations.
The code would look something like this.
-(IBAction) loginButtonPressed:(id) sender {
UIButton *loginButton = (UIButton *) sender;
if (loginButton.selected == NO) {
// Represents user needs to login. Code for login user.
}else
// Represents user needs to logout. Code for logout user.
}
// toggle the login/logout states.
loginButton.selected = !loginButton.selected;
}
You can specify titles/images for the button for normal/selected/highlighted/disabled states.
This would do your job with single button.

You can change the target action by using addTarget and removeTarget, as stated in this related question.
The problem here is to have an elegant way to detect the status of being logged in or not. You can think of a global variable, but it's a bad solution most of the times.
Another alternative is inspecting the UIButton's NSString *title property.
A nice approach is to have a sort of 'session' mechanism as in web applications, which will give you the status application-wide.

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.

How to pass UIAction without touching the UIButton

I've got a UIButton that acts as a switch.
When user taps on it, its state changes to "selected" and action "one" is called. When user taps again UIButton state changes to "not selected" and the action is no longer available.
Is there a way to set the UIButton to "selected" by taping on a completely different UIButton and have it change to "selected" and call the same action as well?
Cheers
From what I have understood from the question, I would like to give you my suggestion
if (!<your_button>.selected)
{
<your_button>.selected = YES;
// do your stuff here
}
else
{
<your_button>.selected = NO;
// do your stuff here, in your case action should be no longer available so that,
<your_button>.userInteractionEnabled = NO;
}
Enjoy Programming !
try like this,'
-(IBAction)nextbutton:(id)sender{
UIButton *btn=(UIButton *)[self.view viewWithTag:tagValue];//pass tag value of that particuler button
btn.selected=YES;
//do whatevr you want.
}
simple thing when you tap on the uibutton make an action for that and in the action for that button , you can set the button state to selected and then in the next line of code you can call that method (action)
- (IBAction)btn1Touched:(id)sender {
[_btn2 setSelected:YES];
[self btn2Touched:self];
}
- (IBAction)btn2Touched:(id)sender {
NSLog(#"btn Action called");
}
UIbutton has state called selected and it is managed via property selected
so to make a button to selected state
[buttonInstance setSelected:YES];
To make it unselected use
[buttonInstance setSelected:NO];
Kindly write a function for that button action like,
-(void)Buttonaction
{
do your action here
also set your button has selected state.
buttonname.setselected=yes;
}
call this function while you are tabbing your button.
Do This:
-(IBAction)switchButtonClicked:(UIButton*)sender
{
if(sender.isSelected)
{
.....
}
else
{
...
}
[sender setSelected:!sender.isSelected];//This will work as Switch.
}
set Selected(Switch ON) and default(Switch OFF) property (image and title) of UIButton from XIB, OR from Code as you want.
With a single button you can do you functionality with this code

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?

iphone navigation & saving data to plist

I'm creating a small iPhone app, when application lauches, it will ask the user to sign up or Login. If they choose sign up safari will open. This part is done.
////button code
button = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
button.frame = CGRectMake(10, 150, 300, 50);
[button setTitle:#"Login" forState:UIControlStateNormal];
button.backgroundColor = [UIColor clearColor];
[button addTarget:self action:#selector(myaction:) forControlEvents:UIControlEventTouchUpInside];
button.adjustsImageWhenHighlighted = YES;
[mainView addSubview:button];
[button release];
If they click Login -
How to navigate to next window asking for username / password ? Can I do it button action ?
2.How I will store their info in plist ( if i'm correct ) ?
Thanks in advance.
One way to do (1.) is:
define a LoginViewController class that inherits from UIViewController
create a nib file named "login" with the UI elements for your login view
make your login button action do somehting like:
LoginViewController *controller = [[LoginViewController alloc] initWithNibName:#"login" bundle:nil];
[self presentModalViewController:controller animated:NO];
There are really several different questions here disguised as one.
1: in the method -buttonAction is where your navigation logic will be. It looks like you're probably working from xibs out of Interface Builder
2: You'll need to use the NSDictionary method called -writeToFile:atomically:. The arguments are the path string for the file to be stored on flash memory, and a BOOL YES/NO value that determines if the file is written immediately, or if it checks for errors first. I'd recommend setting atomically: to YES.
I'm gathering from your question that you're not familiar with Cocoa and UIKit. You'll be hard pressed to get a tutorial on how to put your application together. You're going to need to try Google for swapping views and handling page navigation. It's a lot deeper than what I'm describing here.

How can I safely memory manage a button that I want to remove from the UI?

I'm making an app that is kinda like iBooks. There is some stuff on the screen, each item represented by a small thumbnail. I want the user to be able to delete the items much like when you tap the "Edit" button in iBooks - an X comes up, and the item is deleted. I'm using the delegation pattern to handle all of this, so here is some code:
// Button is created in CustomView.h class
UIImage *deleteImage = [UIImage imageNamed:#"delete.png"];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
self.deleteButton = button;
[self.deleteButton setImage:deleteImage forState:UIControlStateNormal];
[self.deleteButton addTarget:self action:#selector(deleteIt) forControlEvents:UIControlEventTouchUpInside];
// Here's what's called when the delete button is pushed
- (IBAction)deleteMap {
[self.customViewDelegate itemWasDeleted:self];
}
// And here's the implementation of that method, in a View Controller
- (void)itemWasDeleted:self:(CustomView*)customView {
// delete domain object
// . . .
[self.collectionOfCustomViews removeObject:customView];
[customView removeFromSuperview];
}
The problem with this code is that I get a Bad Access Exception. Via NSZombie, looks like this:
* -[UIButton _unhighlight]: message sent to deallocated instance 0x5f4a740
I guess what's happening is that when my target-action implementation is called, it's not yet safe to release the button, as I'm doing in my delegate method. So my question is, what's a better approach to doing this so that may app doesn't crash? I'd like to know the cleanest approach possible.
If collectionOfCustomViews was the only object retaining customView then you released it when you removed it, so it can't respond to removeFromSuperview.