views:

202

answers:

3

I haven't found a very easy way to do this. The ways I've seen require all these timers and stuff. Is there any easy way I can hold a UIButton and cause it to repeat the action over and over until it gets released?

+1  A: 

You can do the following: Make an NSTimer that will start up when the app starts or in viewDidLoad and also make a boolean.

For example:

//Declare the timer, boolean and the needed IBActions in interface.
@interface className {
NSTimer * timer;
bool g;
}
-(IBAction)theTouchDown(id)sender;
-(IBAction)theTouchUpInside(id)sender;
-(IBAction)theTouchUpOutside(id)sender;

//Give the timer properties.
@property (nonatomic, retain) NSTimer * timer;

Now in your implementation file (.m):

//Synthesize the timer
@synthesize timer;
//When your view loads initialize the timer and boolean.
-(void)viewDidLoad {
    g = false;
    timer = [NSTimer scheduledTimerWithInterval: 1.0 target:self selector:@selector(targetMethod:) userInfo:nil repeats: YES];
}

Now make an IBAction for "Touch Down" set the boolean to lets say true. Then make another IBAction button for "Touch Up Inside" and "Touch Up Outside" assign the boolean to false.

For example:

-(IBAction)theTouchDown {
    g = true;
}

-(IBAction)theTouchUpInside {
    g = false;
}

-(IBAction)theTouchUpOutside {
    g = false;
}

Then in that NSTimer method, put the following:(assume g is the boolean you have declared)

-(void) targetmethod:(id)sender {
    if (g == true) {
        //This is for "Touch and Hold"
    }
    else {
        //This is for the person is off the button.
    }
}

I hope this simplifies everything... I know it still uses a timer but there is not another way.

thyrgle
very "hacky" but it works perfectly!
Matt S.
A: 

Unfortunately, it still looks like you have to code this functionality for yourself. simplest way (You still need a timer though):

A function that performs the action you want to repeat:

-(void) actionToRepeat:(NSTimer *)timer
{
    NSLog(@"Action triggered");
}

in your .h file declare and set a property for a timer:

@interface ClassFoo
{
    NSTimer* holdTimer;
}

@synthesize (nonatomic, retain) NSTimer *holdTimer

Then in the .m

@synthesize  holdTimer;

Make two IBActions:

-(IBAction) startAction 
{
holdTimer = [NSTimer scheduledTimerWithTimeInterval:0.4 target:self selector:@selector(actionToRepeat:) userInfo:myDictionary repeats:YES];
}

-(IBAction) stopAction
{
    [holdTimer invalidate];
    holdTimer = nil;
}

Then Just link to the Touch Down event in IB from the button to startAction and the Touch Up Inside to the 'Stop Action'. It isn't a one liner but it allows you to customise the rate the action repeats as well as allowing you to trigger it from another outlet/action.

You might consider subclassing UIButton and adding this functionality if you are going to be using this functionality often - then it is only (slightly) painful to implement the first time.

davbryn
I think invalidate permanently removes the timer, does it not? From the iPhone SDK reference: invalidate: Stops the receiver from ever firing again and requests its removal from its run loop.
thyrgle
Yes - is this not the required functionality? A new timer is then created the next time you press the button
davbryn
A: 

I cannot reply to the first one, but this line:

timer = [NSTimer scheduledTimerWithInterval: 1.0 target:self selector:@selector(targetMethod:) userInfo:nil repeats: YES];

for at least iOS 4.1 and newer needs to be:

timer = [NSTimer scheduledTimerWithTimeInterval: 1.0 target:self selector:@selector(targetMethod:) userInfo:nil repeats: YES];
karlbecker_com