essentially I'm deleting pictures inside of an app.. everything is coded etc.. etc.. so when the user holds the UIButton the image is swapped and has the X over it. Click again and image is deleted from the Doc Directory and DB. So it only made sense to add an alertview before deletion.. problem is that the methods I'm using use (UIButton*)sender as a parameter. I need to pass that parameter to the next method to property delete from the screen.
Is there a relatively simple way to do this..
this is the function that calls the deletion.. the function that would initiate the alertview is also returns a void and takes the same UIButton.
-(void)action:(UIButton*)sender {
if (edit == true)
{
[sender removeFromSuperview];
[[scrollView viewWithTag:[sender tag]] removeFromSuperview];
[self deleteFromDoc:sender];
edit = false;
stop = false;
NSLog(#"remove");
}
}
Change your method to
-(void)action:(UIView *)sender
Assign the tag of the uibutton to the alertview, then in didClickButtonWithIndex: call your action: method passing in the alertView as sender.
Related
I am creating custom dialogs for my app and some what copying UIAlertController in some aspects. How should I implement the behaviour where when you click any action from alert/dialog the controller is dismissed.
How does Apple do it without making us manually specify for each action handler that it should dismiss the view controller?
I have like them one view controller class:
#interface MyAlertViewController : UIViewController
- (void)addAction:(MyAlertAction *) action;
//...
And one class for the actions:
#interface MyAlertAction : NSObject
- (instancetype)initWithTitle:(nullable NSString *)title handler:(void (^)(MyAlertAction *action))handler;
EDIT: How I did it taking in accord the answer feedback:
//MYAlertViewController.m
- (void)viewDidLoad {
for (int i = 0; i < self.actions.count; i++) {
MYAlertAction *action = self.actions[i];
button = [[UIButton alloc] initWithFrame:CGRectZero];
button.tag = i;//this here is how I link the button to the action
[button addTarget:self action:#selector(executeAction:) forControlEvents:UIControlEventTouchUpInside];
[actionStackView addArrangedSubview:button];
[self.actionsStackView addArrangedSubview:actionLayout];
}
}
- (void)executeAction:(UIButton *) sender{
[self dismissViewControllerAnimated:YES completion:^{
//this is where the button tag comes in handy
MYAlertAction *actionToExecute = self.actions[sender.tag];
actionToExecute.actionHandler();
}];
}
How does Apple do it without making us manually specify for each action handler that it should dismiss the view controller?
You are confusing two different things:
The UIAlertAction's last initialization parameter, the handler parameter, which you get to set from outside, and which is to run after the button is tapped and after the alert has been dismissed. It is a block.
The actual button's action, which the client can't set or see. It is configured by the alert controller. It is a selector.
So now, you play the role of the UIAlertController. In your
- (instancetype)initWithTitle:(nullable NSString *)title handler:(void (^)(MyAlertAction *action))handler;
the client hands you the first action I mentioned, the block, and you store it for later execution. But the second action, the button action, the selector, is entirely up to you as you create the button in response to this call.
So as you configure the button, just configure it with a target/action pair that calls into a method of your view controller, just as for any button. In method, when called, the view controller dismisses itself, and in the completion handler of the dismissal, calls the block.
I have three buttons with different actions.Now I don't want to create three IBAction to my buttons.In single IBAction Method can i write the actions for those three buttons.
I am new to Xcode,Can anyone help me to do this...
Thanks in Advance....
try like this
in . h file
#property (strong, nonatomic) IBOutlet UIButton *yourbutton;
in .m
#synthesize yourbutton;
- (IBAction)yourClicked:(id)sender {
UIButton *resultebutton= (UIButton*)sender;
NSString *buttontitle=resultButton.currentTitle;
if ([buttontitle isEqual:#"firstBtitle"]) {
// perform your 1st button action
//call your method
}
else if ([buttontitle isEqual:#"secondBtitle"]) {
// perform your 2nd button action
}
else if ([buttontitle isEqual:#"thirdBtitle"]) {
// perform your 3rd button action
}
}
Assign tag for buttons, and in IBAction method, check Button tag and do action, according to tag of button.
Please correct me, if I get you wrong:
You have three buttons and you want them to trigger the same IBAction. The IBAction itself decides what to do based on which button calls it.
This sounds to me like a perfect example for the "sender" parameter.
Create something like this:
- (IBAction)doSomeAction:(id)sender
{
if ([sender isEqual:self.buttonOne]) {
NSLog(#"ButtonOne");
} else if ([sender isEqual:self.buttonTwo]) {
NSLog(#"ButtonTwo");
} else if ([sender isEqual:self.buttonThree]) {
NSLog(#"ButtonThree");
}
}
With the sender you can identify the button, which calls this method. This way, you can avoid handle tags which can be very annoying to use.
Make sure you connect all three buttons to this action - take a look at the connections inspector. This is very important and a common source for errors. If you remove any connection to an outlet or an IBAction, also check, if this connection ist remove in the Storyboard-object.
If everything is in place just compare the sender with the outlets of the buttons.
Step 1:
Assign your all three buttons different tag in storyboard/XIB,
For ex. firstButton with tag=1, secondButton with tag=2 and thirdButton with tag=3
Step 2:
Define your method like this and bind all your buttons with this method
- (IBAction)buttonAction:(UIButton *)sender
{
if (sender.tag==1) {
NSLog(#"First Button");
} else if (sender.tag==2) {
NSLog(#"Second Button");
} else if (sender.tag==3) {
NSLog(#"Third Button");
}
}
And your work is done.
I have a UITableView that i would like to hide until the user taps the button searchButtonTapped. (I'm also using this button as an IBAction.)
Originally i'm hiding the table view as you see in the viewDidLoad, and i wanna show it after the button was tapped, but it does not shown up after i tap the search button. Do i missed something? For me, it seems it should be work properly, after the button was tapped i refresh the table view.
my .h file
#property (weak, nonatomic) IBOutlet UIButton *searchButtonTapped;
- (IBAction)searchButton:(id)sender;
.m file
- (void)viewDidLoad
{
[super viewDidLoad];
self.tableView.hidden = YES;
}
- (void)buttonTapped:(id)sender {
if (sender == self.searchButtonTapped) {
self.tableView.hidden = NO;
[self.tableView reloadData];
}
}
- (IBAction)searchButton:(id)sender {
[self searchSetup];
}
It's impossible to tell from the little bit of code that you posted. Add NSLog statements in your buttonTapped method that show entering the method, entering the if statement, the value of searchButtonTapped, and the value of self.tableView.
Then you can tell if the method is getting called, if the if statement is evaluating as true, and if the table view is non-nil. One of those things is likely to be the cause of your problem.
I'm guessing that the if statement is wrong. what type is the property self.searchButtonTapped? Post the code that declares that property.
Based on the name I would guess that searchButtonTapped is a boolean?
you have declared only one IBAction, which is for the method searchButton.
This method call the searchSetup´s method. What is the purpose of it?
- (IBAction)searchButton:(id)sender {
[self searchSetup];
}
So you must have another IBAction for buttonTapped method witch is currently a "void" method and not a IBAction. Or you make that connection from the storyBoard, or you must declare it programaticly like:
[self.searchButtonTapped addTarget:self action:#selector(buttonTapped:) forControlEvents:UIControlEventTouchUpInside]
I am trying to save the order in which the buttons are pressed, and then replay that order and run the actions assigned to the buttons in the order they were originally pressed? Can anyone please help me with this?
Each UIControl element has a tag which you can use to be able to identify between the various buttons that are going to be tapped. As each button is tapped, the method (selector) associated with that button will be called (you can even have a single selector be called for all the buttons and differentiate between them via their tags).
As each button is tapped, keep track of which button is tapped by adding the tag of each button to a queue (or in Objective-C: NSMutableArray). Then to replay the actions you can merely read the tag values from the queue and call the corresponding selector.
An example to illustrate:
#property (nonatomic, strong) NSMutableArray *taskArray;
// in your init or viewDidLoad:
_taskArray = [NSMutableArray new];
// in the selector that is called by *all* buttons
-(IBAction) buttonTapped:(id)sender {
[_taskArray addObject:[NSNumber numberWithInteger:sender.tag]];
[self executeActionWithTag:sender.tag];
}
-(void) executeActionWithTag:(NSUInteger)tag {
if(tag == 1) {
// perform specific action 1 ...
} else if (tag == 2) {
// perform specific action 2 ...
}
// ...
}
-(void) replayButtonActions {
for (NSNumber *tag in _taskArray) {
[self executeActionWithTag:[tag integerValue]];
}
}
I have an UIButton that is subview on an UIView. When the button is pressed, my app is supposed to pass a captured image into a function called by the #selector. However, my research shows me that I am not able to pass anything to the function with the selector of the UIButton. How can I go around this?
[hangButton addTarget:self
action:#selector(faceDetector: the image I want to pass in)
forControlEvents:UIControlEventTouchUpInside];
You should trigger your events within a handleButton press method. You don't preset arguments, buttonPress selectors pass one argument, the button that is sending the event.
[hangButton addTarget:self
action:#selector(handleButtonPress:)
forControlEvents:UIControlEventTouchUpInside];
- (void) handleButtonPress:(id)sender {
UIImage * imageToFaceDetect = // get your image
[self faceDetector:imageToFaceDetect];
}