I have some code that creates barbuttonitem Edit and if you click it and begin editing, changes the button to Done.
When I first create the button I set its action to Edit. However, once the user is editing, I want to change the action of the renamed button to Save.
I thought I had save firing but somewhere along the line it stopped working possibly when I added a method in the middle to enable and disable the button.
Can anyone suggest the proper way to change the action of a bar button item?
Here is my code:
//code to create button which sets action to gotoEdit method
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:#"Edit" style:UIBarButtonItemStylePlain target:self action:#selector(gotoEdit)];
self.navigationItem.rightBarButtonItem = editButton;
}
-(void) gotoEdit {
self.navigationItem.rightBarButtonItem.title = #"Done";
_editButton.target = self;
_editButton.action = #selector(save);//changes action to save method
//some other code to make a textview editable, change its background color and so forth.
}
-(void) save {
NSLog(#"save method firing");
}
//I added the following methods at about the same time the save method stopped firing but not sure if they are related. (Probably not but including them anyway.)
//detect change on screen
- (void)textViewDidChange:(UITextView *)textView{
self.didChange=YES;
[self updateSaveButton];
}
-(void) updateSaveButton
{
self.editButton.enabled = (_didChange == TRUE);
}
It is better to use a bool instead of adding and removing the button's action.
-(void) gotoEdit {
if(!isEditing){
// Prep for editing
self.navigationItem.rightBarButtonItem.title = #"Done";
isEditing = true;
}else{
// Prep for saving
self.navigationItem.rightBarButtonItem.title = #"Edit";
isEditing = false;
}
}
For future reference you can remove a button's selector like this:
[_editButton removeTarget:self
action:#selector(gotoEdit)
forControlEvents:UIControlEventTouchUpInside];
Related
I'm building an messaging app, I use JSQMessageViewController to render messages and it's awesome.
Now I have a little problem trying to customize the send button:
Basically I want to replace left and right BarButtonItem to customized button with images.
After some hours of reading and searching, I got this far now:
button without text
button with text
As shown in the pictures, the voice button which is replacing the original send button is disabled if there is no text in the textField, this behavior is not what I want. How do I disable this behavior and make the button available all the time?
And this is how I customize the send button:
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
[rightButton setBackgroundImage:[UIImage imageNamed:#"AudioButton#2x.png"] forState:UIControlStateNormal];
self.inputToolbar.contentView.rightBarButtonItem = rightButton;
if you want button available all the time,
Find This method in "JSQMessagesInputToolbar.h" And Comment These lines in OLD Code
- (void)toggleSendButtonEnabled
{
BOOL hasText = [self.contentView.textView hasText];
// if (self.sendButtonOnRight) {
// self.contentView.rightBarButtonItem.enabled = hasText;
// }
// else {
// self.contentView.leftBarButtonItem.enabled = hasText;
// }
}
in New JSQ Code
- (void)updateSendButtonEnabledState
{
if (!self.enablesSendButtonAutomatically) {
return;
}
BOOL enabled = [self.contentView.textView hasText];
// switch (self.sendButtonLocation) {
// case JSQMessagesInputSendButtonLocationRight:
// self.contentView.rightBarButtonItem.enabled = enabled;
// break;
// case JSQMessagesInputSendButtonLocationLeft:
// self.contentView.leftBarButtonItem.enabled = enabled;
// break;
// default:
// break;
// }
}
this will work if you are replacing your custom button in rightBarButtonItem
add this in viewDidAppear
[self.inputToolbar.contentView.rightBarButtonItem setEnabled:YES];
and override textview delegate
-(void)textViewDidChange:(UITextView *)textView;
iOS unfortunately doesn't have a dropdown picker like html does with the tag. I decided that I was finally going to create one for my app, and it looks and works great. My dropdown object is a subclass of UITextField. However, I changed something and now it only works some of the time.
User interaction is enabled, but I don't want the textfield to be editable. The class in which my dropdown subclass resides is UITextField delegate, and should receive delegate methods for UITextField.
I have - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{ where I check to see if the textfield in question is a dropdown menu, and if it is, I call a method to instantiate a popover and disable editing, but the dropdown only appears on every other tap.
For example, i'll tap the "textfield" and my popover displays. I tap out so the popover goes away, then I tap on the "textfield" and nothing happens. I tap on the textfield once again and the popover appears. No idea why this is happening, here is what i'm doing:
.h
subclass : UIViewController<UITextFieldDelegate>
.m
dropdownTextField.delegate = self;
...
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
if(textField == self.measurementSelect){
NSLog(#"IM CALLED");
[self showPopover:textField];
return NO;
}
return YES;
}
-(void)showPopover:(id)sender{
if (_measurementPicker == nil) {
_measurementPicker = [[iPadMeasurementSelect alloc] initWithStyle:UITableViewStylePlain];
_measurementPicker.delegate = self;
}
if (_measurementPopover == nil) {
_measurementPopover = [[UIPopoverController alloc] initWithContentViewController:_measurementPicker];
[_measurementPopover presentPopoverFromRect:self.measurementSelect.frame inView:self.conversionView permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
else {
[_measurementPopover dismissPopoverAnimated:YES];
_measurementPopover = nil;
}
}
Every tap gets nslogged, so I assume my popover method is the culprit of this problem. Any ideas?
Let's rewrite by teasing apart existence of the UI elements and the visible state of the popover:
// canonical lazy getters for UI elements
- (iPadMeasurementSelect *)measurementPicker {
if (!_measurementPicker) {
_measurementPicker = [[iPadMeasurementSelect alloc] initWithStyle:UITableViewStylePlain];
_measurementPicker.delegate = self;
}
return _measurementPicker;
}
- (UIPopoverController *)measurementPopover {
if (!_measurementPopover) {
_measurementPopover = [[UIPopoverController alloc] initWithContentViewController:self.measurementPicker];
}
return _measurementPopover;
}
// now the show/hide method makes sense. it can take a bool about whether to show or hide
-(void)showPopover:(BOOL)show {
if (show) {
[self.measurementPopover presentPopoverFromRect:self.measurementSelect.frame inView:self.conversionView permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
} else {
[self.measurementPopover dismissPopoverAnimated:NO];
// if you want/need to create a new one each time it is shown, nil the popover here, like this:
// self.measurementPopover = nil;
}
}
When the textField begins editing, show the popover like this:
[self showPopover:YES];
And when the delegate gets the didEndEditing message:
[self showPopover:NO];
i have a Navigation Bar, wich contains a Navigation Item, which contains 2 Bar Buttons, these are created in the Storyboard, and i wanted to change 1 of the buttons at runtime, now this works:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
UINavigationItem *thisNavBar = [self myNavigationItem];
thisNavBar.rightBarButtonItem = nil; // this works, it gets removed
UIBarButtonItem *insertBtn = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:#selector(insertSkemaItem:)];
thisNavBar.rightBarButtonItem = insertBtn; // this also works, it sets the btn
}
Now, in my other method, which is called by another controller, it does not work
- (void)callChildChange {
...
// remove old btn
UINavigationItem *thisNavBar = [self skemaNavigationItem];
thisNavBar.rightBarButtonItem = nil; // does not work?
}
There is nothing wrong with the method, it runs just fine, but the nav btn item does not get removed ?
skemaNavigationItem is a Navigation item, declared in the .h file which links the navigation item i made via the storyboard.
Your UI items need to be added to your code (by ctrl-dragging) in the header file (.h) so they can be publicly accessed from other classes/view controllers.
Presuming you've done this, hiding a UI item is best done by using
relevantClass.yourViewObject.hidden = YES;
or if you really need to delete it for good,
[relevantClass.yourViewObject.view removeFromSuperView];
Edits
Options for changing target method:
Declare #property (nonatomic, assign) BOOL myButtonWasPressed; and:
- (IBAction) myButtonPressed
{
if (!self.myButtonWasPressed)
{
// This code will run the first time the button is pressed
self.myButton.text = #"New Button Text";
self.myButtonWasPressed = YES;
}
else
{
// This code will run after the first time your button is pressed
// You can even set your BOOL property back, and make it toggleable
}
}
or
- (IBAction) myButtonWasPressedFirstTime
{
// do what you need to when button is pressed then...
self.myButton.text = #"New Button Text";
[self.myButton removeTarget:self action:#selector(myButtonPressedFirstTime) forControlEvents:UIControlEventTouchUpInside];
[self.myButton addTarget:self action:#selector(myButtonPressedAgain) forControlEvents: UIControlEventTouchUpInside];
}
- (IBAction) myButtonWasPressedAgain
{
// this code will run the subsequent times your button is pressed
}
I have an edit button, that I obtained through self.editButtonItem and I have set it as self.navigationItem.leftBarButtonItem, such that when it is pressed, a UITableView begins editing and it turns into a "Done" button. When pressed again the view stops editing and the button returns to its normal state.
I would also like an "add" button to turn into a "Clear" button with a different action linked to it when the edit button is pressed.
(Much like in the iPhone "Phone" app's favourites tab, just that the plus button turns into a clear button when the Edit button is pressed).
I would really like to obtain the edit action and style etc in this way (self.editButtonItem), but I would also like to have an extra selector linked to the edit button.
How should I go about doing this? I have tried to create a category for UIBarButtonItem, but I don't really know what I should do with that.
Thanks.
To create a button whose title can change, you can do the following:
Define an ivar for the button:
UIBarButtonItem *_btnAddClear;
In viewDidLoad:
_btnAddClear = [[UIBarButtonItem alloc] initWithTitle:#"Add" style:UIBarButtonItemStyleBordered target:self action:#selector(addClearAction:)];
_btnAddClear.possibleTitles = [NSSet setWithObjects:#"Add", #"Clear", nil];
Since you want this button's title to change when the Edit/Done button is tapped, you can add code like the following:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated];
_btnAddClear.title = editing ? #"Clear" : #"All";
}
And lastly, the button handler:
- (void)addClearAction:(UIBarButtonItem *)button {
if (self.editing) {
// perform "clear" action
} else {
// perform "add" action
}
}
Give tag of UIBarButton such like 101;
and in BarButton Method write following
-(void)barButtonMethod
{
UIBarButtonItem * myButton = (UIBarButtonItem *) sender;
if(sender.tag == 101)
{
yourBtn.tag = 102;
// Write Your first action method such like
[self ActionMethod1];
}
else
{
yourBtn.tag = 101;
// Write Your second action method such like
[self ActionMethod2];
}
}
You don't really need a new action for the editButtonItem.
There is a property that tracks if the UIViewController is in editing state.
#property(nonatomic, getter=isEditing) BOOL editing
In order to do what you want, you can implement the following method in your UITableViewController:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
[super setEditing:editing animated:animated]
//Do your thing
}
just wondering how to make a button "START" that when pressed triggers a function and the text changes to "STOP". then when pressed again the function will stop and the text changes back to "START"
Ive got the button already that starts the function. and i can handle changing the title, just not sure on what to use to make the 1 button have 2 functions
Add the IBAction method like:
- (IBAction)buttonTapped:(id)sender
{
UIButton *btn = (UIbutton *)sender;
NSString *title=btn.titleLabel.text;
if ([title isEqualToString:#"Start"])
{
//Start
}else
{
//Stop
}
}
Please try this:
- (IBAction) buttonAction:(id)sender
{
if([[(UIButton *)sender currentTitle]isEqualToString:#"START"])
{
[actionButton setTitle:#"STOP" forState:UIControlStateNormal];
//start the action here and change the button text to STOP
}
else if([[(UIButton *)sender currentTitle]isEqualToString:#"STOP"])
{
[actionButton setTitle:#"START" forState:UIControlStateNormal];
//stop the action here and change the button text to START
}
}
you have at least two options here:
Check for the title of your button and depending on the value call an action or the other.
Create two different buttons, each one with his action and show/hide them.