Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I have a UIButton in Objective-C and I want to cancel the press if the button is let go before 10 seconds. How would I go about this?
Thanks In Advance
You can use something like this:
[yourButton addGestureRecognizer:[[UILongPressGestureRecognizer alloc]
initWithTarget:self action:#selector(handle:)]];
Create an NSTimer property called timer:
#property (nonatomic, strong) NSTimer *timer;
And a counter:
#property (nonatomic, strong) int counter;
- (void)incrementCounter {
self.counter++;
}
- (void)handle:(UILongPressGestureRecognizer)gesture {
if (gesture.state == UIGestureRecognizerStateBegan) {
self.counter = 0;
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(incrementCounter) userInfo:nil repeats:yes];
}
if (gesture.state == UIGestureRecognizerStateEnded) {
[self.timer invalidate];
}
}
So when the gesture begins start a timer that fires the incrementation method every second until the gesture ends. In this case you'll want to set the minimumPressDuration to 0 otherwise the gesture won't start straight away.
In this way you can get your timer and put a condition on button pressed with self.counter = 10 seconds.
Please let me know if it helps.
To stick with a UIButton's intended design, I would suggest utilizing a UIButton's UIControlEventTouchUpInside and UIControlEventTouchDown control events.
(hint: -addTarget:action:forControlEvents: method)
Logically:
Start a timer on UIControlEventTouchDown
Stop the timer on UIControlEventTouchUpInside
In the UIControlEventTouchUpInside action method
check the timer duration (if 10seconds then perform action else don't)
Example:
Prerequisites:
Declare following objects (in the .h file of the class)
UIButton *btnTest;
NSTimer *tmrTest;
int i_tmrCount;
Code:
- (void)viewDidLoad
{
//...
i_tmrCount = 0;
btnTest = [UIButton buttonWithType:UIButtonTypeCustom];
[btnTest setFrame:CGRectMake(20, 100, 100, 30)];
[btnTest setTitle:#"Test" forState:UIControlStateNormal];
//method connected to the button pressed down event alone
[btnTest addTarget:self action:#selector(btnTestActStart:)
forControlEvents:UIControlEventTouchDown];
//method connected to the button pressed down and released event
[btnTest addTarget:self action:#selector(btnTestAct:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btnTest];
}
- (void)btnTestActStart:(UIButton *)sender
{
tmrTest = [NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:#selector(timerDo)
userInfo:nil
repeats:YES];
}
-(void)timerDo
{
i_tmrCount++;
}
- (void)btnTestAct:(UIButton *)sender
{
//stop the timer
[tmrTest invalidate];
if (i_tmrCount >= 10) {
//do something
NSLog(#"action");
} else {
//do nothing
NSLog(#"reset");
}
//reset i_tmrCount to initial state (to handle next occurrence)
i_tmrCount = 0;
}
PS: If it were a UILabel then go with UILongPressGestureRecognizer but for a UIButton, it won't be ideal because you'll have to drop the implementation of the method connected to the button's UIControlEventTouchUpInside and instead make the method connected to the UILongPressGestureRecognizer as the main button method (it feels kinda dirty)
Related
I'm trying to make a button change color while being pressed for 3 seconds. Once timer reaches 3rd second the color change is permanent but if user releases button before time is up the button goes back to its original color. What I have so far is this:
in viewDidLoad
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(fireSomeMethod)];
longPress.minimumPressDuration = 3.0;
[self.view addGestureRecognizer:longPress];
in fireSomeMethod I have
- (void)someMethod {
[UIView transitionWithView:self.button
duration:2.0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
self.button.backgroundColor = [UIColor redColor];
}
completion:^(BOOL finished) {
NSLog(#"animation finished");
}];
}
This requires me to hold the button down for 3 seconds for the animation to fire and animation itself takes 2 seconds to complete. The desired behavior is that animation starts when longPress starts and I release button before 3 seconds everything goes back to the way it was. Thanks for your help in advance
Make use of button event no need to use UILongPressGestureRecognizer
Make 2 action for your button, one is for Touch Down and other is for Touch Up Inside
like this
// For `Touch Up Inside`
- (IBAction)btnReleased:(id)sender {
[timer invalidate];
NSLog(#"time - %d",timeStarted);
}
// For `Touch Down`
- (IBAction)btnTouchedDown:(id)sender {
timer = [NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:#selector(_timerFired:)
userInfo:nil
repeats:YES];
timeStarted = 0;
}
- (void)_timerFired:(NSTimer *)timer {\
timeStarted++;
}
Create 2 variable timer of type NSTimer and timeStarted of type int. Fire the timer on Touch Down and invalidate it on Touch Up Inside, and in Touch Up Inside action method get the total time till your button is hold.As shown in the above code
I am working video player.. I am using MPMediaplayer framework…
In video player below i am displaying one UIView, in this view i am displaying current video details like Video name and video description and video starting time and ending time… Those are details are displayed in UITableview.
The tableview adding to this uiview..Those are all things are done.
The uiview beside i put one button.. if i click the button then automatically appear uiview. if i click again the uiview disappear..this is also done.
now i am integrating animation for uiview like fade out(means if i click button appear uiview, after 10 seconds automatically disappear the uiview… )..that is my main requirement.. This is also done..
But problem is for example user scroll the uiview (video player details in tableview to scroll the tableview up and down) after 10 seconds automatically disappear. if user scroll the video player details i don’t want to disappear my tableview… but my problem if user scroll the video player details it is automatically disappear after 10 seconds..
so plz help me any body..How to handle this thing…My requirement is if user scroll the video player details i don’t want to disappear my tableview…
- (IBAction)InfoVisibleAction:(id)sender
{
if(UIView.hidden==NO)
{
UIView.hidden=YES;
ScheduleImageView.hidden=YES;
tableView.hidden=YES;
timeLabel1.hidden=YES;
}
else
{
UIView.hidden=NO;
ScheduleImageView.hidden=NO;
tableView.hidden=NO;
timeLabel1.hidden=NO;
[self performSelector:#selector(infoHiddenAction:) withObject:nil afterDelay:10];
}
}
- (IBAction)infoHiddenAction:(id)sender
{
if(UIView.hidden==NO)
{
UIView.hidden=YES;
ScheduleImageView.hidden=YES;
tableView.hidden=YES;
timeLabel1.hidden=YES;
}
}
- (IBAction)infoHiddenAction:(id)sender
{
if(UIView.hidden==NO)
{
SupportedView.hidden=YES;
ScheduleImageView.hidden=YES;
tableView.hidden=YES;
timeLabel1.hidden=YES;
}
}
-(void)viewDidLoad
{
tableView=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 550, 130)];
tableView.delegate=self;
tableView.dataSource=self;
tableView.backgroundColor=[UIColor clearColor];
tableView.scrollEnabled=YES;
tableView.separatorColor=[UIColor clearColor];
[UIView addSubview:tableView];
}
The following should help
In Your class:
#implementation <YourClass> {
NSTimer* hideTimer;
}
Inside (IBAction)InfoVisibleAction:(id)sender
Instead of
[self performSelector:#selector(infoHiddenAction:) withObject:nil afterDelay:10];
Use
[hideTimer invalidate], hideTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(infoHiddenAction:) userInfo:nil repeats:NO];
Implement scrollViewDidScroll
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
[hideTimer invalidate], hideTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:#selector(infoHiddenAction:) userInfo:nil repeats:NO];
}
Inside (IBAction)infoHiddenAction:(id)sender
Add
[hideTimer invalidate];
How can I perform an action on the down press of the return key, not the up press? textFieldShouldReturn: only allows the up press.
Alternately, how can I have a UIActivityIndicatorView animate at the beginning of an IBAction on button up press? Even if it is called first, it doesn't animated until the end, and at that time, it is told to stop animating.
EDIT:
For the second question, here's what happens:
- (IBAction)buttonPressed:(id)sender {
[indicator startAnimating];
//do stuff...
usleep(3000000) //to illustrate the problem, wait 3 seconds
}
The indicator should start animating first, but it starts animating after the usleep(). How do I make it animate before anything else?
For the latter question use UIControlEventTouchUpInside.
For example...
....
[yourButton addTarget:self action:#selector(didTchUp)forControlEvents:UIControlEventTouchUpInside];
- (void)didTchUp {
[yourUIActivityIndicatorView startAnimating];
}
usleep() doesn't work because the display is only updated once the main thread returns, at least I think this is why. But a good solution is NSTimer...
[NSTimer scheduledTimerWithTimeInterval:3.0
target:self
selector:#selector(targMtod:)
userInfo:nil
repeats:NO];
[yourTextField addTarget:self action:#selector(someAction:) forControlEvents:UIControlEventEditingDidEndOnExit];
About UIActivityIndicatorView you should alloc and then init it. Then UIButton add a subview activityIndicatorView, when you press a button, the action contains [activityIndicatorView startAnimating]
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 9 years ago.
Improve this question
I have a button set up as an IBAction that i was to disable after it's pressed and re-enable it after 12 seconds. I have a bunch of timers set up in the IBAction. It's called moodButton. How do I disable this?
I like the flexibility of #iBuntyM's answer.
Here's an even more flexible approach, using Grand Central Dispatch:
- (IBAction)buttonPressed:(id)sender {
UIButton *button = (UIButton *)sender;
button.enabled = NO;
dispatch_after(
dispatch_time(DISPATCH_TIME_NOW, 12 * NSEC_PER_SEC),
dispatch_get_main_queue(), ^{
button.enabled = YES;
});
}
EDIT Of course alot can happen in 12 seconds and when the timer fires you might find you don't want to re-enable the button any more. Also it's difficult (impossible?) to cancel a dispatch timer if these conditions change before it fires.
Therefore perhaps using an NSTimer, stored in an instance variable, is a better approach as it can be cancelled (invalidated) if you change your mind/conditions change.
For example:
.h file:
#interface MyView : UIView {
NSTimer *_reenableButtonTimer;
}
#end
.m file:
- (IBAction)buttonPressed:(id)sender {
UIButton *button = (UIButton *)sender;
_reenableButtonTimer = [NSTimer scheduledTimerWithTimeInterval:12.0f
target:self
selector:#selector(reenableButton:)
userInfo:button
repeats:NO];
}
- (void)reenableButton:(NSTimer *)timer {
UIButton *button = (UIButton *)[timer userInfo];
button.enabled = YES;
}
The _reenableButtonTimer can then be invalidated before fire time to cancel this re-enabling.
On press action disable the UIButton and then you can use performSelector:withObject:afterDelay
call another function and enable the UIButton again with afterDelay pass the delay time.
- (IBAction)buttonPressed:(UIButton *)sender {
[sender setEnabled:YES];
[self performSelector:#selector(enableButton:) withObject:sender afterDelay:12.0];
}
-(void)enableButton:(UIButton *)button {
[button setEnabled:NO];
}
As there is no need to create IBOutlet for UIButton as another answer doing you can pass the UIButton object and change the property as required.
Try with following code;
-(IBAction) buttonClickEvent:(UIButton *) sender
{
sender.enable = NO;
[NSTimer scheduledTimerWithTimeInterval:12.f target:self selector:#selector(moodButton:) userInfo:nil repeats:NO];
}
Code of NSTimer method
- (void)moodButton:(NSTimer *)theTimer
{
self.moodButton.enable = YES;
}
Implemented the following:
- (IBAction)buttonPressed:(UIButton *)button {
button.enabled = NO; // Same as setting enabled property to self.moodButton
[self performSelector:#selector(enableMoodButtonButton) withObject:button afterDelay:12.0];
}
- (void)enableMoodButtonButton:(UIButton *)button {
button.enabled = YES;
}
You can put things conditional into your IBAction like
-(IBAction)pushMe {
if(isThisActionAvailable) {
[self doMyWorkNow];
}
}
EDIT
Maybe I have described the problem incorrectly. Let me add that this segmented controller is controlling the speed of a NSTimer with the following code.
- (IBAction) segmentAction:(id)sender
{
speed = [[speeds objectAtIndex:[sender selectedSegmentIndex]] integerValue];
}
- (IBAction)startPause: (UIButton *)sender{
NSString *buttonTitle = sender.currentTitle;
if ([buttonTitle isEqualToString: #"Pause"]) {
[self.myButton setTitle:#"Resume" forState:UIControlStateNormal];
[timer invalidate];
}
else
{
[self.myButton setTitle:#"Pause" forState:UIControlStateNormal];
if ([self.deal length]>cardNum) {
timer = [NSTimer scheduledTimerWithTimeInterval:speed
target:self
selector:#selector(dealCard)
userInfo:nil
repeats:YES];
}
else
{
[timer invalidate];
}
}
}
When the user taps any of the segments in the segmentedController BEFORE tapping the startPause button, the NSTimer works fine. Nut if the user taps the startPause button before tapping a segment, no (desired) delays occur from the NSTimer. Does this help explain the situation any better?
EDIT
I have a UISegmentedControl in Storyboard and want to initialize it. It would be especially nice to initialize it in the Storyboard itself. The image below shows how the Med segment is selected, but when the app starts, Med is NOT selected; rather the user has to trigger a Value changed event. How do I get it selected, initially? One of the other questions here on SO suggested the following code, but I have not figured out how to associate the UISegmentedControl in my Storyboard with the name segmentControl.
segmentControl.selectedSegmentIndex=-1;