Guys i need to call a function in such a view that if there is no user interaction for three seconds the function should be called
what should i do?
Can any one pls give a logic or link which help this?
Thanks
My recommendation is to override - (void)touchesBegan: withEvent: on that view.
When you receive a touch event, set a timer, and make its time 3 seconds. If you receive a touch and there is a timer, change its fire date to be 3 seconds after the touch time. When the timer fires, call the function, and set the timer to nil.
You can play with the movement, removals and cancellation methods to make your timer fire correctly and at the right time for the activity required.
Use NSTimer as:-
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
if ([touch view] == self.view)
{
NSTimer *updateTimer = [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:#selector(updateTime) userInfo:nil repeats:YES];
}
}
-(void)updateTime
{
NSLog(#"....Update Function Called....");
[self functionName];
}
Use this for calling function.Check it Hope it helps.Thanks :)
Related
I'm trying to develop a new application for iOS but I'm stuck with NSTimer :-(. Currently I have a void function which hides an UIButton after the user taps twice or more on the screen and a NSTimer. I want to make the button visible again after the NSTimer reaches 5 seconds and stop and reset it right after in order to re-hide it after the user taps twice again :-) but I don't know how to tell the app that 5 seconds have passed :-/.
Can someone help me, please? :-)
Here's the code so far :-)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSUInteger numTaps = [[touches anyObject] tapCount];
if (numTaps >= 2)
{
// Other code//
[self.button setHidden:YES];
buttonHideTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 invocation:nil repeats:NO];
// Other code //
}
}
Thanks!
The timer needs to have a selector, which will tell the timer what to do after the time has passed:
buttonHideTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:#selector(showButtonNow) userInfo:nil repeats:NO];
I'm wondering if someone knows how to implement the "touch up inside" response when a user pushes down then lifts their finger in the touchesBegan, touchesEnded methods. I know this can be done with UITapGestureRecognizer, but actually I'm trying to make it so that it only works on a quick tap (with UITapGestureRecognizer, if you hold your finger there for a long time, then lift, it still executes). Anyone know how to implement this?
Using the UILongPressGesturizer is actually a much better solution to mimic all of the functionality of a UIButton (touchUpInside, touchUpOutside, touchDown, etc.):
- (void) longPress:(UILongPressGestureRecognizer *)longPressGestureRecognizer
{
if (longPressGestureRecognizer.state == UIGestureRecognizerStateBegan || longPressGestureRecognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint touchedPoint = [longPressGestureRecognizer locationInView: self];
if (CGRectContainsPoint(self.bounds, touchedPoint))
{
[self addHighlights];
}
else
{
[self removeHighlights];
}
}
else if (longPressGestureRecognizer.state == UIGestureRecognizerStateEnded)
{
if (self.highlightView.superview)
{
[self removeHighlights];
}
CGPoint touchedPoint = [longPressGestureRecognizer locationInView: self];
if (CGRectContainsPoint(self.bounds, touchedPoint))
{
if ([self.delegate respondsToSelector:#selector(buttonViewDidTouchUpInside:)])
{
[self.delegate buttonViewDidTouchUpInside:self];
}
}
}
}
I'm not sure when it was added, but the property isTouchInside is a life saver for any UIControl derived object (e.g. UIButton).
override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
super.endTracking(touch, with: event)
if isTouchInside {
// Do the thing you want to do
}
}
Here's the Apple official docs
You can implement touchesBegan and touchesEnded by creating a UIView subclass and implementing it there.
However you can also use a UILongPressGestureRecognizer and achieve the same results.
I did this by putting a timer that gets triggered in touchesBegan. If this timer is still running when touchesEnded gets called, then execute whatever code you wanted to. This gives the effect of touchUpInside.
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSTimer *tapTimer = [[NSTimer scheduledTimerWithTimeInterval:.15 invocation:nil repeats:NO] retain];
self.tapTimer = tapTimer;
[tapTimer release];
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([self.tapTimer isValid])
{
}
}
You can create some BOOL variable then in -touchesBegan check what view or whatever you need was touched and set this BOOL variable to YES. After that in -touchesEnded check if this variable is YES and your view or whatever you need was touched that will be your -touchUpInside. And of course set BOOL variable to NO after.
You can add a UTapGestureRecognizer and a UILongPressGestureRecognizer and add dependency using [tap requiresGestureRecognizerToFail:longPress]; (tap and long press being the objects of added recognizers).
This way, the tap will not be detected if long press is fired.
I have a variable called touchStatus that tracks the touch status in the program. The variable gets set to B in the touchesBegan method, E in touchesEnded and to M in touchesMoved.
However, my requirements are a little different. I was requested to program in a way so that there is one second of delay between the finger being lift off from the screen and touchStatus getting set to E. If the user touches the screen before the one second elapses, touchStatus should continue to be M or B (whatever it was before the one second).
How can I accomplish this?
You can use
[self performSelector:#selector(setEndedValue:) withObject:self afterDelay:1.0];
Create a BOOL to monitor whether the value should be set such as:
BOOL hasTouchRestarted = NO;
If the screen is touched again before the value is set, change the value to YES and return from the setEndedValue method.
-(void)setEndedValue {
if ( hasTouchRestarted ) { return; }
// set value
self.touchStatus = E;
}
In the touchEnded routine set up an NSTimer task to invoke a selector in one second. If there is another touch before then, cancel the timer task.
Use a NSTimer *timer ivar to initiate a delayed call, and cancel the call if the user lifts the finger before one second.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
self.myvar = #"B";
[self.timer invalidate];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(handleOneSecondPress) userInfo:nil repeats:NO];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent*)event {
[self.timer invalidate];
self.timer = nil;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
self.myvar = #"M";
}
- (void)handleOneSecondPress {
self.timer = nil;
self.myvar = #"E";
}
In my game I need to calculate duration of touch. I did this by :
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
self.endTime = [NSDate date]; //NSDate *endTime in .h
NSLog(#"%#",self.endTime);
}
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
tStart = [[NSDate date] timeIntervalSinceDate:self.endTime];
NSLog(#"duration %f",tStart);
I am using this time interval as a factor to calculate height of the jump the player makes.
Less is the tStart, low is the jump and more is the tStart, high is the jump. I am doing this as :
if(tStart/1000<=9.430)
{
[player jump:5.0f];
}
else if(tStart>9.430 && tStart<=9.470)
{
[player jump:7.0f];
}
else if(tStart/1000>9.470)
{
[player jump:8.0f];
}
However I want to perform this action on tochBegan so that player may jump as soon as screen is touched. For this need the value of tStart in touchBegan. How should I do that?
Thanks
For a given touch, the UITouch instance is the same, so at ccTouchBegan save the touch/touches with the oldest timestamp and then wait for ccTouchEnded. When you get the UITouch that you previously saved, it means the player lifted the finger.
update
You can
Jump as soon as the user touches the screen.
Jump and boost the jump while the touch is ongoing up to x milliseconds (suggestion from grapefrukt).
Jump when the user releases the touch or a max time of x milliseconds has elapsed.
Jump and boost the jump until the touch is over.
Option 4 is unpractical because the user can keep pressing as long as he wants. So given that you want to make a variable jump, here is code for option 3:
UITouch *jump = nil;
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
// no jump ongoing, start one
if (jump==nil){
jump = touch;
// jump on a separate thread
[NSThread performSelectorInBackground:(SEL)jump withObject:touch];
}
}
-(void) jump:(UITouch*) touch {
NSInterval time = [touch timestamp]; // I *think* this is the time since system uptime :P
int jumpSpeed = 1;
// increase the jump speed for every 100ms up to 'maxTimeYouAreAllowedToJump' ms
while ( ([NSProcessInfo systemUptime]-time < maxTimeYouAreAllowedToJump) && (jump!=nil) ){
jumpSpeed += 1;
[NSThread sleepForTimeInterval:.1]; // sleep for 100ms
}
[self doTheJumpingWithSpeed:jumpSpeed]; // do the actual jump!
}
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
// user released the touch that initiated the jump
if ((touch!=nil) && (touch==jump)) {
jump =nil;
}
}
I'd like to support pre 3.2 and this is the only symbol that doesn't want to cooperate, anyone know of some touchesmoved code or something i can use in lieu of the UILongPressGestureRecognizer?
Thanks,
Nick
As you know, you should use touchesBegan, Moved, Ended, and Canceled functions for pre 3.2 iOS.
I think implementing only touchesMoved is bad because if the user presses and doesn't move at all until releasing, then touchesMoved won't get called ever.
Instead, I used NSTimer to acheive a long press touch event.
This might not be an optimal solution, but it worked well for my app.
Here's a snippet of code.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
isAvailable = NO;
timer = [NSTimer scheduledTimerWithTimeInterval:DURATION target:self selector:#selector(didPassTime:) userInfo:nil repeats:NO];
}
- (void)didPassTime:(id)sender{
isAvailable = YES;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if(isAvailable == YES){
// still pressing after 0.5 seconds
}
else{
// still pressing before 0.5 seconds
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
if(isAvailable == YES){
// releasing a finger after 0.5 seconds
}
else {
// releasing a finger before 0.5 seconds
[timer invalidate];
timer = nil;
}
}