I have an IBAction that displays what is being pressed on certain buttons to a UILabel. I have another IBAction for equalPressed button that does many things, but I also added titleDisplay.text = nil; It works perfectly the first time. Then after I press the equalPressed button it doesn't show up. I know it is because i have titleDisplay.text set to nil. However, I don't know how to clear the UILabel with the equalPressed button so my other buttons can be displayed on the screen without appending constantly
First IBAction
- (IBAction) titleLabel: (UIButton *) sender {
NSString *titleOfButton = [[sender titleLabel] text];
titleDisplay.text = [[titleDisplay text] stringByAppendingString: titleOfButton];
}
Second IBAction
- (IBAction) equalPressed: (UIButton *) sender {
titleDisplay.text = nil;
}
The reason why this would work only the first time is because when you assign nil to an object, you're essentially dumping your reference to it. You should instead set the text to an empty string, like so:
[titleDisplay setText:#""];
Try
- (IBAction) equalPressed: (UIButton *) sender {
titleDisplay.text = #"";
}
Related
How to get the pressed button title text value and to shows as other pressed button if pressed?i have used the following code to get the title text from button
- (IBAction) checkIt:(id)sender
{
UIButton *button = (UIButton *)sender;
NSLog(#"Button text value %#", button.titleLabel.text);
}
How to show the button text into other button if i pressed? Please help me to resolve this
Do like this,
- (IBAction) checkIt:(id)sender
{
UIButton *button = (UIButton *)sender;
[your_other_button setTitle:button.titleLabel.text forState:UIControlStateNormal];
}
you need to Create Globle Variable at your app-delegate like:-
yourAppdelegate.h
#property (strong, nonatomic) NSString *buttonTitleCopy;
yourAppdelegate.m
#synthesize buttonTitleCopy;
now you just get this variable at your Particular Class like:-
yourClass.h
#import "yourAppdelegate.h"
//create Object of your Delegate Class
yourAppdelegate *objAppdelegate;
yourClass.m
- (void)viewDidLoad
{
objAppdelegate = (REMAppDelegate *) [[UIApplication sharedApplication]delegate];
[super viewDidLoad];
}
now in your Method:-
- (IBAction) checkIt:(id)sender
{
UIButton *button = (UIButton *)sender;
objAppdelegate.buttonTitleCopy=button.titleLabel.text
NSLog(#"Button text value %#", delegate.buttonTitleCopy);
}
now you can use buttonTitleCopy variable anywere in your project with app-delegate class Object. Hope your getting this and you solve your issue.
NOTE:- just set your OtherButton Title with
otherButton.titleLabel.text=objAppdelegate.buttonTitleCopy;
You can try this way
- (IBAction) checkIt:(id)sender
{
otherButton.titleLabel.text=sender.titleLabel.text;
}
you can get it to point tags or just make a variable button and add it to your button. And get btn text.
I have a tableviewcontroller with a uinavigation bar that has a barbuttonitem, called editBarButton. When editBarButton is pressed I want my tableview to be updated with a new button in each of the cells that says 'Edit'. What is the correct way to implement this?
- (void)onEditBarButtonPressed{
//TODO: update cells
}
You have to overwrite the accessoryView attribute in your UITableViewCell with your Edit button:
Create a custom button to overwrite the current accesoryView:
- (UIButton *) makeDetailDisclosureButton
{
UIButton * button = [UIButton yourEditButton];
[button addTarget: self
action: #selector(accessoryButtonTapped:withEvent:)
forControlEvents: UIControlEventTouchUpInside];
return ( button );
}
Then the button will call this routine when it's done, which then feeds the standard UITableViewDelegate routine for accessory buttons:
- (void) accessoryButtonTapped: (UIControl *) button withEvent: (UIEvent *) event
{
NSIndexPath * indexPath = [self.tableView indexPathForRowAtPoint: [[[event touchesForView: button] anyObject] locationInView: self.tableView]];
if ( indexPath == nil )
return;
[self.tableView.delegate tableView: self.tableView accessoryButtonTappedForRowWithIndexPath: indexPath];
}
You can see a similar question here: Using a custom image for a UITableViewCell's accessoryView and having it respond to UITableViewDelegate
I found a solution to my problem.
You should add a object level BOOL flag called editPressed.
It should be set to NO in viewDidLoad.
When making each cell, add a button to each and set it to hidden if need be:
[button setHidden:!editPressed];
It is important to use the flag so that when new cells are made they will keep the buttons hidden if they should be or visible otherwise.
Then have a object level NSMutableArray * of the buttons in the view controller and add each button to it:
[buttons addObject:button];
When you want to show each button, just change the hidden state:
editPressed = YES;
for(int i = 0; i != [butttons count]; i++){
[[buttons objectAtIndex:i] setHidden:!editPressed];
}
When you want to hide each button, once again, change the hidden state:
editPressed = NO;
for(int i = 0; i != [butttons count]; i++){
[[buttons objectAtIndex:i] setHidden:!editPressed];
}
- (IBAction)onClick1:(id)sender {
// Make sure it's a UIButton
if (![sender isKindOfClass:[UIButton class]])
return;
NSString *title = [(UIButton *)sender currentTitle];
}
I understand how to get the title and other current values but I don't see how I can get the value of the tag property.
I've got a test project here where I just used:
NSInteger i = [sender tag];
You can simply call:
NSInteger the_tag = ((UIView*)sender).tag;
Each UIButton is a subclass of UIView which contains the tag property.
When an IBAction is called:
-(IBAction) onClick1: (id) sender;
What is passed in the sender? Since it's hooked up through the IB, I'm not really sure. My question is how to get the text of the button to be the passed object (NSString most likely) so that I could call it inside the action implementation.
-(IBAction) onClick1: (id) sender {
NSLog(#"User clicked %#", sender);
// Do something here with the variable 'sender'
}
The sender should be the control which initiated the action. However, you should not assume its type and should instead leave it defined as an id. Instead, check for the object's class in the actual method as follows:
- (IBAction)onClick1:(id)sender {
// Make sure it's a UIButton
if (![sender isKindOfClass:[UIButton class]])
return;
NSString *title = [(UIButton *)sender currentTitle];
}
It's actually:
-(IBAction) onClick1: (id) sender {
NSLog(#"User clicked %#", sender);
// Do something here with the variable 'sender'
}
sender is not a NSString, it's of type id. It's just the control that sent the event. So if your method is trigged on a button click, the UIButton object that was clicked will be sent. You can access all of the standard UIButton methods and properties programmatically.
-(IBAction)onClick:(id) sender {
UIButton *btn = (UIButton *)sender;
//now btn is the same object. And to get title directly
NSLog(#"Clicked button: %#",[[btn titleLabel] text]);
}
Simply write the following code
-(IBAction) getButtonTitle:(id)sender
{
UIButton *button = (UIButton *)sender;
NSString *buttonTitle = button.currentTitle;
NSLog(#"Button Title %#",buttonTitle);
}
Thats it... you have done!!!
Sender should be defined as type id, not int or NSString. The sender is the actual object that's calling the method; if you hooked it up to a button, it will be a UIButton, if it's a text field, a UITextField. You can use this to get information from the control (for example the text field's current string value), or compare it to an IBOutlet instance variable if you have multiple controls hooked up to the same action method.
You can just use the following to get the button label and determine which one was clicked:
NSLog(#"Clicked button: %#",[[sender titleLabel] text]);
To answer your question, the id is the object from the IB.
To fetch the text from the button:
NSLog(#"Date::%#",[btn titleForState:UIControlStateNormal]);
I use the "Next" value for the "Return Key" to get the Next button in place of the Done button, but (obviously) pressing it doesn't automatically move to the next UITextField in my view.
What's the right way to do this? On a larger topic, what are some tips for properly building forms in the iPhone SDK?
Make some object the first text field's delegate, and implement the - (BOOL)textFieldShouldReturn:(UITextField *)textField method; in that, call the second text field's -becomeFirstResponder. Returning YES from that will make the text field perform its default behavior for the return button – I think that's generally sending its action message. If you don't have anything added as a target of that action, it doesn't really matter what you return.
To build on Noah's answer, if you have a lot of textfields and don't feel like having a bunch of if's, you could do it this way:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
//[[self.view viewWithTag:textField.tag+1] becomeFirstResponder];
UIView *view = [self.view viewWithTag:textField.tag + 1];
if (!view)
[textField resignFirstResponder];
else
[view becomeFirstResponder];
return YES;
}
Once you tag every textfield starting at any number, as long as they're tagged sequentially, in storyboard or in code, it should work.
For Swift:
func textFieldShouldReturn(textField: UITextField) -> Bool {
//your collection of textfields
guard let i = textFields.indexOf(textField) else { return false }
if i + 1 < textFields.count {
textFields[i + 1].becomeFirstResponder()
return true
}
textField.resignFirstResponder()
return true
}
This seems to work quite well and doesn't require the tag system many are suggesting. There are 2 things to note with this solution though:
All the UITextFields must be in the same UIView (have the same superview).
The UITextFields need to be in the right order in the interface builder.
-(BOOL)textFieldShouldReturn:(UITextField *)textField {
/*
* 1. Loop through the textfield's superview
* 2. Get the next textfield in the superview
* 3. Focus that textfield
*/
UIView *superView = [textField superview];
BOOL foundCurrent = false;
for (UITextField *tf in superView.subviews) {
// Set focus on the next textfield
if (foundCurrent) {
[tf becomeFirstResponder];
return NO;
}
//Find current textfield
if ([tf isEqual:textField]) {
foundCurrent = true;
}
}
return YES;
}
I don't like to deal with tag so here is my solution. Create an IBOutletCollection of all your textFields in your ViewController, drag to connect your textFields in order from top to bottom.
#interface ViewController () <UITextFieldDelegate>
#property (strong, nonatomic) IBOutletCollection(UITextField) NSArray *allTextFields;
#end
In viewDidLoad set your textFields delegate. (Or set it in storyboard).
for (VVTextField *tf in self.allTextFields) {
tf.delegate = self;
}
Then implement UITextField Delegate
#pragma mark - UITextField Delegate
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
NSUInteger currentIndex = [self.allTextFields indexOfObject:textField];
NSUInteger nextIndex = currentIndex+1;
if (nextIndex < self.allTextFields.count) {
[[self.allTextFields objectAtIndex:nextIndex] becomeFirstResponder];
} else {
[[self.allTextFields objectAtIndex:currentIndex] resignFirstResponder];
}
return YES;
}
I've been struggling with this issue too...and as a result I've created small library for handling multiple textfields. You can find it on github GNKeyboardAwareScrollView#GNTextFieldsManager.
You can initialise it with array of textfields:
NSArray *myTextFields = #[...]; // the order of array matters!
GNTextFieldsManager *manager = [[GNTextFieldsManager alloc] initWithTextFields:myTextFields];
Or by specifying parent view (and setting tags for all views):
GNTextFieldsManager *manager = [[GNTextFieldsManager alloc] initWithView:self.view];
Hope i'll be useful for somebody :)