UIButton, how to prevent double actions taking place
I'm not quite sure how UIButton works. For example, if I have a timer that goes off when I hit the start button, how do I make it so that if the button gets pressed again, it doesn't start another timer. Cause then my timer is going twice as fast. It seems like I'd want to invalidate my original timer if the button gets pressed twice and start a new timer, but I don't know how you开发者_高级运维 can tell if the button gets pressed twice.
Also, is there a way to change the label on the UIButton once its pressed once, and then have it revert back when it gets pressed again? Like, Play/Pause? Thanks.
Encapsulation and state management are very useful for situations like this. Depending on how much you wish to encapsulate, you might consider having a new object to be modified by the UIButton (you mention Play/Pause so I'm imagining some kind of media player?)
(You might consider an enumeration
of states in this example to make it more extendable, but for simplicity I'll use a BOOL
)
@interface MediaManager : NSObject
{
BOOL isPlaying; // whether
NSTimer *playTimer; // timer used exclusively by the media manager
//... other vars relating to type of media/selected track etc anything related
}
-(void) togglePlay;
@property (nonatomic, synthesize) NSTimer *playTimer;
@propety (nonatomic, assign) BOOL isPlaying;
@end
@implementation MediaManager
@synthesize playTier, isPlaying;
- (void)togglePlay
{
if (!self.isPlaying)
{
if (self.playTimer == nil) // if it hasn't already been assigned
{
self.playTimer = [NSTimer ...]; // create and schedule the timer
self.isPlaying = YES;
}
}
else
{
if (self.playTimer != nil)
{
// get the timer and invalidate it
self.isPlaying = NO;
}
}
}
@end
This is not the best though out example, but by encapsulating the state within a seperate object, your view UIButton
can rely solely on the model state for presenting itself (assuming it holds a reference to an initialized Media Manager
:
-(IBAction) buttonPressed: (id) sender
{
[self.mediaManager togglePlay]; // play from whatever state it is in
// update the button text to reflect state
if (self.mediaManager isPlaying)
{
self.mediaButton.textLabel.text = @"Pause";
}
else
{
self.mediaButton.textLabel.text = @"Play";
}
}
This way you don't have to include the state handling each time you want to use this functionality, and the button always reflects the true state of the object it is acting on.
You might go a step further and encapsulate the state strings in the object also, which could be queried in a similar manner.
(Apologies for poorly written code, I've not had a coffee yet)
If your timer is not nil, somebody has already set it, which means the button has already been pressed. Consider:
@interface MyController : UIViewController {
@private NSTimer *timer;
}
- (IBAction)pressButton: (id)sender;
@end
@implementation MyController
- (IBAction)pressButton: (id)sender {
if (!self->timer) {
self->timer = [NSTimer scheduledTimer...];
}
}
@end
精彩评论