I have an application that responds to user input, but there are segments where there is animation effects that I don't want the user to be able to interrupt in any way. To accomplish this, I have a class that is linked/instantiated with any object/scene that should respond to user input. Each method in that class (began, moved, ended) checks the following class-level "allowInput" method before doing any further processing:
// application-level flag indicating if user touch/click input is currently enabled...
static BOOL g_fAllowUserInput_ = YES;
// these class-level methods can be called from multiple threads, so create a single-thread-only
// lock for accessing the current mode...
#import <pthread.h>
static pthread_mutex_t _mutexSerializeCurrentModeAllowInput = PTHREAD_MUTEX_INITIALIZER;
// global class methods to handle application-wide user touch/click input permissions...
@implementation TouchHandler ( Allow )
// report if user touch/click input is allowed...
+ ( BOOL ) allowUserInput
{
// access the single-thread-only lock...
pthread_mutex_lock( &_mutexSerializeCurrentModeAllowInput );
// get the current mode...
BOOL const mode = g_fAllowUserInput_;
// release the single-thread-only lock...
pthread_mutex_unlock( &_mutexSerializeCurrentModeAllowInput );
// return the current "touch enabled" status...
return mode;
} // end TouchHandler ( Allow )::allowUserInput
// enable/disable user touch/click input...
+ ( void ) setAllowUserInput: ( BOOL const ) allow
{
// access the single-thread-only lock...
pthread_mutex_lock( &_mutexSerializeCurrentModeAllowInput );
// regardless of what the current status is, we need to unschedule the automatic "force allow input"
// method, if it's running, since the application is still functioning properly...
[ [ [ CCDirector sharedDirector ] scheduler ] unscheduleSelector: @selector( forceAllowInput: )
forTarget: self
];
// set the new "input enabled" status...
g_fAllowUserInput_ = allow;
// if user input is supposed to be suspended...
if ( ! allow )
{
// schedule the automatic "force allow input" method, to make sure that we don't block out the
// user if something gets "screwy" in the application...
[ [ [ CCDirector sharedDirector ] scheduler ] scheduleSelector: @selector( forceAllowInput: )
forTarget: self
interval: 5.0f
paused: NO
];
} // end disable user input
// release the single-thread-only lock...
pthread_mutex_unlock( &_mutexSerializeCurrentModeAllowInput );
return;
} // end TouchHandler ( Allow )::setAllowUserInput
// scheduled method to force-enable user input if it's been disabled for an unexpected duration...
+ ( void ) forceAllowInput: ( ccTime ) delta
{
// access the single-thread-only lock...
pthread_mutex_lock( &_mutexSerializeCurrentModeAllowInput );
// remove this method from the scheduler, since it's only necessary to fire it once...
[ [ [ CCDirector sharedDirector ] scheduler ] unscheduleSelector: @selector( forceAllowInput: )
forTarget: self
];
// set the new "input enabled" status to "enabled"...
g_fAllowUserInput_ = YES;
// release the single-thread-only lock...
pthread_mutex_unlock( &_mutexSerializeCurrentModeAllowInput );
return;
} // end TouchHandler ( Allow )::forceAllowInput
@end // end @implementation TouchHandler ( Allow )
"setAllowUserInput" is called at various places in the application, depending on whether or not I want user interaction to be suspended.
My question is: Is there a more efficient way of handling this on an almost-application-wide scale? I say "almost" because there is at least one control, a button, that captures the current screen and sends it as an email attachment, and that control needs to always be active. The scheduled delay of 5 seconds is an arbitrary value that I chose, but I hate doing things like that, so I'm looking for a way to have the application "sense" when something is wrong and user interaction has been disabled for too long.
Thanks for any help you can give....