ios - Using a Long Press Gesture only if certain conditions are met -


i trying create long press gesture presents second view controller, once press has been held 3 seconds. however, want second view controller presented if device in accelerometer orientation entire 3 seconds. is, if gesture not held long enough or device tilted much, gesture dismissed , user must try again.

// in firstviewcontroller.h

#import <uikit/uikit.h> #import <coremotion/coremotion.h>  @interface firstviewcontroller : uiviewcontroller  @property (nonatomic, strong) cmmotionmanager *motionmanager;  @end 

// in firstviewcontroller.m

#import "firstviewcontroller" #import "secondviewcontroller"  @implementation motionmanager;  - (void) viewdidload {     [super viewdidload];     self.motionmanager = [[cmmotionmanager alloc]init];     uilongpressgesturerecognizer *longpress = [[uilongpressgesturerecognizer alloc]initwithtarget:self action:@selector(handlelongpress:)];     longpress.minimumpressduration = 3.0;     [self.view addgesturerecognizer:longpress]; }  - (void) handlelongpress: (uilongpressgesturerecognizer *)sender {     // not sure here } 

i have tried chunks of code in last method looks obnoxious , not correct. instead, have listed several lines of code below know work individually, need assistance in making them work together.

// accelerometer

if ([self.motionmanager isaccelerometeravailable]) {     nsoperationqueue *queue = [[nsoperationqueue alloc]init];     [self.motionmanager startaccelerometerupdatestoqueue:queue withhandler:^(cmaccelerometerdata *accelerometerdata,nserror *error)     {         if (abs(accelerometerdata.acceleration.x) < 0.3 && abs(accelerometerdata.acceleration.y) < 0.30 && abs(accelerometerdata.acceleration.z) > 0.70) // phone flat , screen faces         {              nslog(@"correct orientation!!!");             [self.motionmanager stopaccelerometerupdates];         }         else         {             nslog(@"incorrect orientation!!!");             [self.motionmanager stopaccelerometerupdates];         }]; }  else {     nslog(@"accelerometer not available."); } 

// go second view controller

if (sender.state == uigesturerecognizerstatebegan) {     secondviewcontroller *svc = [self.storyboard instantiateviewcontrollerwithidentifier:@"secondviewcontroller"];     [self presentviewcontroller:svc animated:yes completion:nil]; } 

any ideas? or more general way cancel gesture unless condition met helpful.

i hope code verbose enough read, it's pretty self explanatory - i've stuck accelerometer code, , used same variable names.

#import "viewcontroller.h" #import <coremotion/coremotion.h>  @interface viewcontroller () {      nsoperationqueue    *motionqueue;     nstimer             *touchtimer;     nstimeinterval      initialtimestamp;     bool                touchvalid;      float                timerpollinseconds;     float                longpresstimerequired; }  @property (strong, nonatomic)            nstimer             *touchtimer; @property (assign, nonatomic)            nstimeinterval      initialtimestamp; @property (assign, nonatomic)            bool                touchvalid; @property (assign, nonatomic)            float               timerpollinseconds; @property (assign, nonatomic)            float               longpresstimerequired; @property (strong, nonatomic)            cmmotionmanager     *motionmanager; @property (strong, nonatomic)            nsoperationqueue    *motionqueue;   @end  @implementation viewcontroller  @synthesize touchtimer = _touchtimer, initialtimestamp, touchvalid, motionqueue = _motionqueue; @synthesize timerpollinseconds, longpresstimerequired, motionmanager = _motionmanager;  - (void)viewdidload {     self.timerpollinseconds = 0.25f;     self.longpresstimerequired = 3.0f;     self.touchtimer = nil;     self.touchvalid = no;     self.initialtimestamp = nstimeintervalsince1970;     self.motionmanager = [[cmmotionmanager alloc] init];     self.motionqueue = [[nsoperationqueue alloc] init];     [_motionqueue setname:@"motionqueue"];     [_motionqueue setmaxconcurrentoperationcount:nsoperationqueuedefaultmaxconcurrentoperationcount];      [super viewdidload];      self.view.multipletouchenabled = no; }  - (void)didreceivememorywarning {     [super didreceivememorywarning];     // dispose of resources can recreated. }  #pragma mark - operations  -(void) startlongpressmonitorwithtimestamp:(nstimeinterval) timestamp {     nslog(@"starting monitoring - %g", timestamp);     if( self.touchtimer ) {         if( [_touchtimer isvalid] ) {             [_touchtimer invalidate];         }     }      self.touchtimer = [nstimer timerwithtimeinterval:self.timerpollinseconds target:self selector:@selector(timerpolled:) userinfo:nil repeats:yes];      if( [_motionmanager isaccelerometeravailable] ) {         nslog(@"accelerometer available");         if( ![_motionmanager isaccelerometeractive] ) {             nslog(@"starting accelerometer");             [_motionmanager startaccelerometerupdatestoqueue:self.motionqueue withhandler:^(cmaccelerometerdata *accelerometerdata, nserror *error) {                  if (abs(accelerometerdata.acceleration.x) < 0.3 && abs(accelerometerdata.acceleration.y) < 0.30 && abs(accelerometerdata.acceleration.z) > 0.70) // phone flat , screen faces                 {                     dispatch_sync(dispatch_get_main_queue(), ^{                         self.touchvalid = yes;                     });                 }                 else                 {                     dispatch_sync(dispatch_get_main_queue(), ^{                         self.touchvalid = no;                         [self stoplongpressmonitoring:yes];                     });                 };             }];         }         else {             nslog(@"accelerometer active");         }     }     else {         nslog(@"accelerometer not available");     }      self.initialtimestamp = timestamp;      self.touchvalid = yes;     [_touchtimer fire];      [[nsrunloop mainrunloop] addtimer:self.touchtimer formode:nsrunloopcommonmodes]; }    -(void) stoplongpressmonitoring:(bool) touchsuccessful {     [_motionmanager stopaccelerometerupdates];     [_touchtimer invalidate];     self.touchvalid = no;      if( touchsuccessful ) {         nslog(@"yes");     }     else {          nslog(@"no");     } }  #pragma mark - user interaction -(void) touchesbegan:(nsset *)touches withevent:(uievent *)event {      //we're using current times, interval since touches timestamp refers system boot     // more feasible use boot time, simplicity, i'm using     nstimeinterval timestamp = [nsdate timeintervalsincereferencedate];     [self startlongpressmonitorwithtimestamp:timestamp]; }  -(void) touchesended:(nsset *)touches withevent:(uievent *)event {     if( self.touchvalid && [nsdate timeintervalsincereferencedate] - self.initialtimestamp == self.longpresstimerequired ) {         [self stoplongpressmonitoring:yes];     }     else {         [self stoplongpressmonitoring:no];     } }    #pragma mark - timer call -(void) timerpolled:(nstimer *) timer {     nstimeinterval firedtimestamp = [nsdate timeintervalsincereferencedate];     nslog(@"timer polled - %g", firedtimestamp);     if( self.touchvalid ) {         nslog(@"time elapsed: %d", (int)(firedtimestamp - self.initialtimestamp));          if( firedtimestamp - self.initialtimestamp >= self.longpresstimerequired ) {             nslog(@"required time has elapsed");             [self stoplongpressmonitoring:yes];         }     }     else {         nslog(@"touch invalidated");         [self stoplongpressmonitoring:no];     } }   @end 

Comments

Popular posts from this blog

c++ - Creating new partition disk winapi -

Android Prevent Bluetooth Pairing Dialog -

VBA function to include CDATA -